> ## Documentation Index
> Fetch the complete documentation index at: https://docs.semicola.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a reporting pipeline

> Read delivery into your application: answer an agent question with get_delivery, refresh a dashboard, or download aggregates as CSV.

Semicola can feed a dashboard, a daily reporting job or an agent that checks performance. First decide
which you need.

| Outcome                                | Use                                                           | Who runs the schedule |
| -------------------------------------- | ------------------------------------------------------------- | --------------------- |
| Answer an agent's delivery question    | v3 MCP `get_delivery` with explicit metrics and scope         | Your client           |
| Refresh a dashboard or warehouse table | `get_delivery`, or REST `GET /api/v2/buyer/reporting/metrics` | Your application      |
| Download aggregate data as CSV         | REST reporting with `download=true`                           | Your application      |

A CSV aggregate isn't a raw event feed, and a notification isn't a report.

## 1. Prove access and pick the report

Over MCP, call `get_status` and check the account. Then pick the report:

* A Buyer account uses `report: "campaign_delivery"`.
* A Seller account uses `report: "seller_delivery"`, or `campaign_delivery` for advertisers on its
  own supply (name the advertiser, campaign or media buy).

Over REST, use an API key (see [API keys](/guides/api-keys)); an MCP OAuth token isn't a REST
credential.

## 2. Read a bounded window

```json get_delivery theme={null}
{
  "report": "campaign_delivery",
  "metrics": ["impressions", "clicks", "spend", "ctr"],
  "dimensions": ["date", "campaign", "media_buy"],
  "range": { "startDate": "2026-09-01", "endDate": "2026-09-07" },
  "filters": { "campaignId": "CAMPAIGN_ID" },
  "limit": 25
}
```

* **Metrics**: `impressions`, `clicks`, `spend`, `ctr`, `cpm`, `views`, `video_completions`, `vcr`,
  `viewable_impressions`, `conversions`, `conversion_value`, `pacing`.
* **Dimensions**: `date`, `campaign`, `media_buy`, `package`, `seller`, `sales_agent`, `buyer`,
  `product`.
* **Range**: dates up to 90 days apart, or `lifetime`. A `packageId` filter needs dates.
* **Paging**: `limit` up to 1,000; pass the returned `cursor` for the next page. See
  [Pagination](/v3/pagination).

Ask for the metrics you'll use rather than everything.

## 3. Refresh on a schedule

Your application owns the schedule. Re-read a trailing window each run (sellers can restate recent
days), and upsert rows keyed on the dimensions you asked for. Keep windows bounded and page through
results.

## 4. Download CSV

`GET /api/v2/buyer/reporting/metrics` takes `advertiserId`, `campaignId`, `mediaBuyId`, `startDate`
and `endDate` (or `days`), and `view`. Add `download=true` to get a `downloadUrl`, `expiresAt`,
`fileName` and `rowCount`. The `downloadUrl` is signed for your account over the query and expires
7 days after it's issued; request it with the same credential to get the CSV. An altered or expired
link answers `403` ("This download link expired. Request the report again."). Sending
`Accept: text/csv` with `download=true` returns the file directly, without a link. In the app,
**Export CSV** on the Reporting view downloads the same rows.

## Not available yet

* Scheduled delivery to your own cloud storage (log-level data delivery).
* A seller `margin` report.
* A credential-free download link: `downloadUrl` is signed and expires, but still needs your
  credential.

## Related

* [Reporting](/buy/reporting)
* [Webhooks](/buy/webhooks)
