---
title: Bring your own creative
description: Add an image or a video that you own from its URL, and register it into the provider library of one advertiser, so that an ad there can use it. All from your AI client.
---

You have an image or a video, and you want an ad of one advertiser to use it. Ask your agent. With the four `asset_*` tools, the agent adds the file to AdCrunch as an Asset. Then it registers the Asset into the provider library of that advertiser.

## Two words

This job uses two words of AdCrunch: an [Asset](/concepts#asset) and a [Registration](/concepts#registration). An Asset belongs to your organization. A Registration puts an Asset in the provider library of one [advertiser](/concepts#advertiser), and one Asset can have a Registration with each of your advertisers.

:::info[You register into an advertiser, not into a provider]

Your organization can have several advertisers on one provider. Each Registration names one advertiser. The agent finds the advertiser with [`list_advertisers`](/mcp/tools/list-advertisers).

:::

## The job, step by step

### 1. Ask for the Asset

> "Add https://example.com/spring-sale.mp4 to AdCrunch."

The agent calls [`asset_create`](/mcp/tools/asset-create) with the public `https` URL of the file. AdCrunch creates an Asset at `pending`, and the call returns at once. In the background, AdCrunch fetches the file from the URL and stores it. The bytes do not pass through the conversation.

:::info[An agent that holds the bytes uploads them]

An agent that has a local file and no URL calls [`asset_create_upload`](/mcp/tools/asset-create-upload). The call returns an upload URL on `*.r2.cloudflarestorage.com`. The agent sends an HTTP `PUT` with the bytes to that URL, with the header `If-None-Match: *`. The URL can create the file once, and it can never replace it. An agent that cannot reach that host needs a public URL for the file, or it uses the REST API with an API key.

:::

### 2. The agent waits for the Asset to be ready

The agent calls [`asset_get`](/mcp/tools/asset-get) until `status` is `ready`. AdCrunch reads the header of the file, and checks its type and its size. A file that passes becomes a `ready` Asset of your organization. When the file fails, the Asset is `failed`, and `failureCode` and `failureReason` say why. To try again, the agent creates a new Asset.

### 3. The agent can read the Asset

A `ready` Asset shows in the Assets of your organization, and [`asset_list`](/mcp/tools/asset-list) lists it.

### 4. The agent registers the Asset

> "Put it in the Acme Meta account."

The agent calls [`asset_register`](/mcp/tools/asset-register) with the Asset and the advertiser. The call returns at once, with a `running` Registration. The provider takes the file in the background.

### 5. The agent checks until the Registration settles

> "Is the video ready in the Acme account yet?"

The agent calls [`asset_get`](/mcp/tools/asset-get), and reads the Registration with that advertiser. An image is ready as soon as the provider takes it. A video can stay `running` for several minutes while the provider processes it. That is normal, and it is not a failure. When the Registration is `ready`, you see the id that the provider gave the file, and an ad of that advertiser can use the file.

To see the Assets of your organization, ask:

> "What creative do we have, and where is each file registered?"

The agent calls [`asset_list`](/mcp/tools/asset-list). Each Asset comes with its Registrations.

## What AdCrunch accepts

| Kind  | Types                | Largest file |
| ----- | -------------------- | ------------ |
| Image | GIF, JPEG, PNG, WebP | 30 MiB       |
| Video | MP4, QuickTime (MOV) | 4 GiB        |

AdCrunch checks the stored bytes. AdCrunch deletes a file that fails the check, and the Asset is `failed`. `failureCode` holds one of these codes:

- `too_large`: the file is over the limit for its kind.
- `unsupported_type`: the bytes are a type that is not in the table. AdCrunch reads the type from the bytes, and a `Content-Type` is only a hint.
- `unreadable`: the file ends before its header does.
- `source_unreachable`: AdCrunch could not fetch the file from the URL.
- `source_length_unknown`: the source did not send a `Content-Length`.

A provider can have lower limits of its own. When the provider refuses a file, the Registration is `failed`, and the Asset stays with your organization.

## The state of a Registration

| State | What it means | What the agent does |
| --- | --- | --- |
| `running` | The provider takes or processes the file. | It checks again later with `asset_get`. |
| `ready` | The file is in the provider library of the advertiser, with the id of the provider. | It can build an ad from the Asset. |
| `failed` | The Registration failed. `failureReason` gives the reason. When AdCrunch refused the advertiser, `failureCode` gives a code. | It registers the Asset again with `asset_register`. It does not create the Asset again. When `failureCode` is `provider_not_connected` or `missing_write_access`, it asks you to reconnect the provider first. |

[`asset_list`](/mcp/tools/asset-list) shows `ready` Assets only. [`asset_get`](/mcp/tools/asset-get) answers an Asset in every status: `pending`, `ready` or `failed`. A `failed` Asset carries `failureCode` and `failureReason`. [`asset_register`](/mcp/tools/asset-register) accepts a `ready` Asset only. It answers `asset_not_ready` for a `pending` Asset and `asset_failed` for a `failed` Asset.

## Guardrails

- **A Registration puts nothing live.** It makes a file available to an ad of one advertiser. It creates no ad and spends no money. On Meta, the agent builds an ad creative from a registered Asset with [`meta_create_creative`](/mcp/tools/meta-create-creative), which needs `mutation:write`.
- **Its own scopes.** The two reads need `asset:read`. The creation of an Asset and the Registration need `asset:write`. None of them needs `mutation:write`, because a file in a provider library changes no delivery. See [Auth & scopes](/mcp/auth).
- **No copy in the provider library.** While an Asset has a `running` or `ready` Registration with an advertiser, a second Registration with that advertiser fails with `already_registered`. When the agent registers again after a `failed` Registration, AdCrunch replaces the failed one. So a retry is safe.
- **Your organization only.** An Asset or an advertiser that is not in your organization gives `not_found`. An id that does not exist gives the same answer, so nobody can find out whether an id is real.
- **A failed Registration is not a failed Asset.** When the Registration fails, the Asset stays with your organization. The agent registers it again, and does not create the Asset again.

Each failed call carries a code. [Errors](/mcp/errors) describes the shape of a failed call. [What to expect](/mcp/what-to-expect) states the rules that each tool follows, such as which organization your client acts for.

## Providers

AdCrunch registers files into the libraries of Meta and TikTok. Meta takes the bytes from AdCrunch. TikTok fetches the file itself, and applies its own limits to it. [What each provider supports](/connect/providers#register-creative) states what happens with an advertiser of another provider.

## The tools of this job

- [`asset_list`](/mcp/tools/asset-list): list the Assets of your organization, each with its Registrations.
- [`asset_get`](/mcp/tools/asset-get): read one Asset, and the state of each Registration.
- [`asset_create`](/mcp/tools/asset-create): create an Asset from the URL of a file.
- [`asset_create_upload`](/mcp/tools/asset-create-upload): create an Asset from bytes that the agent holds, and get an upload URL.
- [`asset_register`](/mcp/tools/asset-register): register an Asset into the provider library of one advertiser.
