> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-snap-format-preview-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Artifacts

> Artifacts in AdCP represent the content context adjacent to ad placements, enabling brand suitability evaluation without exposing raw content.

# Artifacts

An **artifact** is a unit of content adjacent to an ad placement. When evaluating brand suitability, you're asking: "Is this artifact appropriate for my brand's ads?"

## What Is an Artifact?

Artifacts represent the content context where an ad appears:

* A **news article** on a website
* A **podcast segment** between ad breaks
* A **video chapter** in a YouTube video
* A **social media post** in a feed
* A **scene** in a CTV show
* An **AI-generated image** in a chat conversation

Artifacts are identified by `property_id` + `artifact_id` - the property defines where the content lives, and the artifact\_id is an opaque identifier for that specific piece of content. The artifact\_id scheme is flexible - it could be a URL path, a platform-specific ID, or any consistent identifier the property owner uses internally.

## Structure

**Schema**: [artifact.json](https://adcontextprotocol.org/schemas/v3/content-standards/artifact.json)

Web article:

```json theme={null}
{
  "property_id": {"type": "domain", "value": "reddit.com"},
  "artifact_id": "r_fitness_post_abc123",
  "assets": [
    {"type": "text", "role": "title", "content": "Best protein sources for muscle building", "language": "en"},
    {"type": "text", "role": "paragraph", "content": "Looking for recommendations on high-quality protein sources...", "language": "en"},
    {"type": "image", "url": "https://cdn.reddit.com/fitness-image.jpg", "alt_text": "Person lifting weights"}
  ]
}
```

Podcast segment (note: no `url` — the property is identified by `apple_podcast_id`, and the audio asset uses a secured URL):

```json theme={null}
{
  "property_id": {"type": "apple_podcast_id", "value": "1234567890"},
  "artifact_id": "episode_42_segment_3",
  "assets": [
    {"type": "text", "role": "title", "content": "The Future of Running Shoes", "language": "en"},
    {"type": "audio", "url": "https://cdn.example.com/secured/ep42_seg3.mp3", "transcript": "Today we're talking to Dr. Chen about biomechanics research...", "duration_ms": 480000}
  ],
  "metadata": {
    "json_ld": [{"@type": "PodcastEpisode", "episodeNumber": 42}]
  }
}
```

CTV scene (the artifact\_id encodes show, season, episode, and scene):

```json theme={null}
{
  "property_id": {"type": "app_id", "value": "com.streamingservice.tv"},
  "artifact_id": "show_running_s2e5_scene_14",
  "assets": [
    {"type": "text", "role": "title", "content": "Championship Race - Final Stretch", "language": "en"},
    {"type": "video", "url": "https://cdn.streaming.example.com/secured/s2e5_scene14.mp4", "transcript": "The runners round the final corner as the crowd erupts...", "duration_ms": 120000}
  ]
}
```

### Required Fields

| Field         | Description                                                                                               |
| ------------- | --------------------------------------------------------------------------------------------------------- |
| `property_id` | Where this artifact lives - uses standard identifier types (`domain`, `app_id`, `apple_podcast_id`, etc.) |
| `artifact_id` | Unique identifier within the property - the property owner defines their scheme                           |
| `assets`      | Content in document order - text blocks, images, video, audio                                             |

### Optional Fields

| Field              | Description                                                             |
| ------------------ | ----------------------------------------------------------------------- |
| `variant_id`       | Identifies a specific variant (A/B test, translation, temporal version) |
| `format_id`        | Reference to format registry (same as creative formats)                 |
| `url`              | Web URL if the artifact has one                                         |
| `metadata`         | Artifact-level metadata (Open Graph, JSON-LD, author info)              |
| `published_time`   | When the artifact was published                                         |
| `last_update_time` | When the artifact was last modified                                     |

## Variants

The same artifact may have multiple variants:

* **Translations** - English version vs Spanish version
* **A/B tests** - Different headlines being tested
* **Temporal versions** - Content that changed on Wednesday

Use `variant_id` to distinguish between them:

```json theme={null}
// English version
{
  "property_id": {"type": "domain", "value": "nytimes.com"},
  "artifact_id": "article_12345",
  "variant_id": "en",
  "assets": [
    {"type": "text", "role": "title", "content": "Breaking News Story", "language": "en"}
  ]
}

// Spanish translation
{
  "property_id": {"type": "domain", "value": "nytimes.com"},
  "artifact_id": "article_12345",
  "variant_id": "es",
  "assets": [
    {"type": "text", "role": "title", "content": "Noticia de última hora", "language": "es"}
  ]
}

// A/B test variant
{
  "property_id": {"type": "domain", "value": "nytimes.com"},
  "artifact_id": "article_12345",
  "variant_id": "headline_test_b",
  "assets": [
    {"type": "text", "role": "title", "content": "Alternative Headline Being Tested", "language": "en"}
  ]
}
```

The combination of `artifact_id` + `variant_id` must be unique within a property. This lets you track which variant a user saw and correlate it with delivery reports.

## Asset Types

Assets are the actual content within an artifact. Everything is an asset - titles, paragraphs, images, videos.

### Text

```json theme={null}
{"type": "text", "role": "title", "content": "Article Title", "language": "en"}
{"type": "text", "role": "paragraph", "content": "The article body text...", "language": "en"}
{"type": "text", "role": "description", "content": "A summary of the article", "language": "en"}
{"type": "text", "role": "heading", "content": "Section Header", "heading_level": 2}
{"type": "text", "role": "quote", "content": "A quoted statement"}
```

Roles: `title`, `description`, `paragraph`, `heading`, `caption`, `quote`, `list_item`

Each text asset can have its own `language` tag for mixed-language content.

### Image

```json theme={null}
{
  "type": "image",
  "url": "https://cdn.example.com/photo.jpg",
  "alt_text": "Description of the image"
}
```

### Video

```json theme={null}
{
  "type": "video",
  "url": "https://cdn.example.com/video.mp4",
  "transcript": "Full transcript of the video content...",
  "duration_ms": 180000
}
```

### Audio

```json theme={null}
{
  "type": "audio",
  "url": "https://cdn.example.com/podcast.mp3",
  "transcript": "Today we're discussing...",
  "duration_ms": 3600000
}
```

## Metadata

Artifact-level metadata describes the artifact as a whole, not individual assets:

```json theme={null}
{
  "metadata": {
    "author": "Jane Smith",
    "canonical": "https://example.com/article/12345",
    "open_graph": {
      "og:type": "article",
      "og:site_name": "Example News"
    },
    "json_ld": [
      {
        "@type": "NewsArticle",
        "datePublished": "2025-01-15"
      }
    ]
  }
}
```

This is separate from assets because it's about the artifact container, not the content itself.

## Secured Asset Access

Many assets aren't publicly accessible - AI-generated images, private conversations, paywalled content. The artifact schema supports authenticated access.

### Pre-Configuration (Recommended)

For ongoing partnerships, configure access once during onboarding rather than per-request:

1. **Service account sharing** - Grant the verification agent access to your cloud storage
2. **OAuth client credentials** - Set up machine-to-machine authentication
3. **API key exchange** - Share long-lived API keys during setup

This happens during the activation phase when the seller first receives content standards from a buyer.

### Per-Asset Authentication

When pre-configuration isn't possible, include access credentials with individual assets:

```json theme={null}
{
  "type": "image",
  "url": "https://cdn.openai.com/secured/img_abc123.png",
  "access": {
    "method": "bearer_token",
    "token": "eyJhbGciOiJIUzI1NiIs..."
  }
}
```

**Note on token size**: For artifacts with many assets, per-asset tokens can significantly increase payload size. Consider:

1. **Pre-configured access** - Set up service account access once during onboarding
2. **Shared token reference** - Define tokens at the artifact level and reference by ID
3. **Signed URLs** - Use pre-signed URLs where the URL itself is the credential

The `url` field is the access URL - it may differ from the artifact's canonical/published URL. For example, a published article at `https://news.example.com/article/123` might have assets served from `https://cdn.example.com/secured/...`.

### Access Methods

| Method            | Use Case                                                                |
| ----------------- | ----------------------------------------------------------------------- |
| `bearer_token`    | OAuth2 bearer token in Authorization header                             |
| `service_account` | GCP/AWS service account credentials                                     |
| `signed_url`      | Pre-signed URL with embedded credentials (URL itself is the credential) |

### Service Account Setup

For GCP:

```json theme={null}
{
  "access": {
    "method": "service_account",
    "provider": "gcp",
    "credentials": {
      "type": "service_account",
      "project_id": "my-project",
      "private_key_id": "...",
      "private_key": "-----BEGIN PRIVATE KEY-----\n...",
      "client_email": "verification-agent@my-project.iam.gserviceaccount.com"
    }
  }
}
```

For AWS:

```json theme={null}
{
  "access": {
    "method": "service_account",
    "provider": "aws",
    "credentials": {
      "access_key_id": "AKIAIOSFODNN7EXAMPLE",
      "secret_access_key": "...",
      "region": "us-east-1"
    }
  }
}
```

### Pre-Signed URLs

For one-off access without sharing credentials:

```json theme={null}
{
  "type": "video",
  "url": "https://storage.googleapis.com/bucket/video.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=...&X-Goog-Signature=...",
  "access": {
    "method": "signed_url"
  }
}
```

The URL itself contains the credentials - no additional authentication needed.

## Property Identifier Types

The `property_id` uses standard identifier types from the AdCP property schema:

| Type                    | Example                                 | Use Case         |
| ----------------------- | --------------------------------------- | ---------------- |
| `domain`                | `reddit.com`                            | Websites         |
| `app_id`                | `com.spotify.music`                     | Mobile apps      |
| `apple_podcast_id`      | `1234567890`                            | Apple Podcasts   |
| `spotify_collection_id` | `4rOoJ6Egrf8K2IrywzwOMk`                | Spotify podcasts |
| `youtube_channel_id`    | `UCddiUEpeqJcYeBxX1IVBKvQ`              | YouTube channels |
| `rss_url`               | `https://feeds.example.com/podcast.xml` | RSS feeds        |

## Artifact ID Schemes

The property owner defines their artifact\_id scheme. Examples:

| Property Type | Artifact ID Pattern                         | Example                  |
| ------------- | ------------------------------------------- | ------------------------ |
| News website  | `article_{id}`                              | `article_12345`          |
| Reddit        | `r_{subreddit}_{post_id}`                   | `r_fitness_abc123`       |
| Podcast       | `episode_{num}_segment_{num}`               | `episode_42_segment_2`   |
| CTV           | `show_{id}_s{season}e{episode}_scene_{num}` | `show_abc_s3e5_scene_12` |
| Social feed   | `post_{id}`                                 | `post_xyz789`            |

The verification agent doesn't need to understand the scheme - it's opaque. The property owner uses it to correlate artifacts with their content.

## Related

* [Content Standards Overview](.) - How artifacts fit into the content standards workflow
* [calibrate\_content](./tasks/calibrate_content) - Sending artifacts for calibration
