# Declare AI contribution

Generative AI contribution is declared through a single attribute, `ai-contribution`. It uses the **same name and the same four values** on every resource that can carry a declaration, so you only have to learn it once.

## The four values

| Value | Meaning |
| -- | -- |
| `undeclared` | No declaration has been made. This is the default value. |
| `none` | Declared as containing no AI contribution. |
| `partly` | AI contributed in part. |
| `entirely` | Entirely generated by AI. |

### `undeclared` is not `none`

The distinction is deliberate:

- `none` means the client **declares** that no AI was involved.
- `undeclared` means **no declaration has been made**. It is the default value, including on your entire catalog predating this feature.

A silence is never turned into a declaration. Do not map missing data in your own system to `none` — send nothing at all, or send `undeclared`.

## Where to declare it

Four things can carry a declaration, each on its own resource:

| What | Resource | Attribute | What the declaration qualifies |
| -- | -- | -- | -- |
| Credit | [`roles`](../api/roles) | `ai-contribution` | The degree of AI contribution of **that specific credit** |
| Static album cover | [`products`](../api/products) | `cover-ai-contribution` | The degree of AI contribution of the static cover artwork |
| Album motion art | [`asset-attachments`](../api/asset-attachments) | `ai-contribution` | The degree of AI contribution of the animated artwork |
| Video | [`videos`](../api/videos) | `ai-contribution` | The degree of AI contribution of the video |

Note that `products` uses `cover-ai-contribution`, not `ai-contribution`: the declaration is about the cover artwork specifically, not about the release as a whole.

### `partly` is meaningful on assets, not just on credits

`partly` is not reserved for credits. It has a real meaning on artwork and video: a photographic cover retouched with generative fill or outpainting is `partly`, as is a video mixing filmed footage with generated shots.

### There is no track-level attribute

A track does not carry a declaration of its own. The track level is **derived from its credits**. If you are looking for an `ai-contribution` attribute on the `tracks` resource, there isn't one by design — declare on the credits instead, via [`roles`](../api/roles).

## Write semantics

:::warning

This is the part to get right. An integration that re-sends the attribute on every update can silently overwrite existing declarations in bulk.

:::

The same three rules apply on all four resources:

| Payload | Effect |
| -- | -- |
| Attribute **absent** | No-op. The current value is left untouched. |
| `"undeclared"` | Resets the declaration to "not declared". |
| `"none"` / `"partly"` / `"entirely"` | Records the declaration. |

### Declaring

```http
PATCH https://api.idol.io/api/v2/roles/99e73ff1b87f37d1198ed50240796c18f1d2588c
Content-Type: application/vnd.api+json
```

```json
{
  "data": {
    "type": "roles",
    "id": "99e73ff1b87f37d1198ed50240796c18f1d2588c",
    "attributes": { "ai-contribution": "partly" }
  }
}
```

The same on a static cover, a motion art and a video:

```json
{
  "data": {
    "type": "products",
    "id": "1",
    "attributes": { "cover-ai-contribution": "entirely" }
  }
}
```

```json
{
  "data": {
    "type": "asset-attachments",
    "id": "42",
    "attributes": { "ai-contribution": "partly" }
  }
}
```

```json
{
  "data": {
    "type": "videos",
    "id": "7",
    "attributes": { "ai-contribution": "none" }
  }
}
```

### Leaving a declaration alone

Simply omit the attribute. This payload updates the product name and does not touch the cover declaration:

```json
{
  "data": {
    "type": "products",
    "id": "1",
    "attributes": { "name": "New title" }
  }
}
```

### Clearing a declaration

Send `undeclared` explicitly:

```json
{
  "data": {
    "type": "products",
    "id": "1",
    "attributes": { "cover-ai-contribution": "undeclared" }
  }
}
```

## Credits are a projection

:::warning

A declaration made on a credit does not survive a regeneration of the credits.

:::

`roles` records are **recomputed** from the product's raw roles every time the product moves to `active` status, and on every forced role creation. Moving a product back to draft and re-activating it therefore regenerates its credits and **clears the declarations they carried**.

This is intended behaviour, not a bug. In practice:

- A declaration set through `PATCH /roles/:id` is not guaranteed to be stable if the product goes back through draft status.
- After a re-activation, the declarations have to be submitted again.
- If your workflow toggles products between draft and active, re-apply the declarations as the last step, after the product is active.

Cover, motion art and video declarations are not affected — they live on their own records and are not regenerated.

## Cover and motion art are two independent declarations

Declaring one does **not** declare the other.

An album whose cover is a normal photograph but whose motion art was generated by AI is declared on the corresponding `asset-attachments` record, and `products.cover-ai-contribution` stays untouched. The reverse is equally true.
