---
title: "A campaign's measured payout report: per-clip 48h/7d numbers, totals, estimated payout and the public report link"
method: GET
path: "/api/v1/campaigns/{id}/proof"
---

# A campaign's measured payout report: per-clip 48h/7d numbers, totals, estimated payout and the public report link

`GET /api/v1/campaigns/{id}/proof`

## Request

- Base URL: `https://everpop.app`
- URL: `https://everpop.app/api/v1/campaigns/{id}/proof`
- Auth: HTTP bearer

## Path parameters

- `id` string, required

## Query parameters

- `csv` string

## Response `200`

The payout report as JSON, or with ?csv a CSV download (one row per post).

- CampaignProofEnvelope
  - `ok` unknown, required
  - `data` object, required
    - `campaign` object, required
      - `id` string, required
      - `name` string, required
      - `sourceUrl` string, nullable, required
      - `sourceVideoId` string, nullable, required
      - `sourceVideoTitle` string, nullable, required
      - `platformRule` string, required
      - `cpmCents` integer, nullable, required
      - `budgetCents` integer, nullable, required
      - `deadline` string, date-time, nullable, required
      - `status` 'ACTIVE' | 'COMPLETED', required
    - `briefLines` string[], required: The brief rules every attached post passed.
    - `items` ProofItem[], required: The campaign's published posts, newest first.
      - `postId` string, required
      - `title` string, nullable, required
      - `publishedUrl` string, nullable, required
      - `postedAt` string, date-time, nullable, required
      - `outcomes` object, required
        - `h48` ProofWindow, required
          - `views` number, nullable, required
          - `averageViewPercentage` number, nullable, required
          - `likes` number, nullable, required
          - `subscribersGained` number, nullable, required
          - `measuredAt` string, date-time, required
        - `d7` ProofWindow, required
          - `views` number, nullable, required
          - `averageViewPercentage` number, nullable, required
          - `likes` number, nullable, required
          - `subscribersGained` number, nullable, required
          - `measuredAt` string, date-time, required
      - `platform` 'TIKTOK' | 'INSTAGRAM_REELS' | 'YOUTUBE_SHORTS' | 'FACEBOOK_REELS' | 'THREADS', required: Only YouTube Shorts are measured; posts on other platforms carry no outcomes.
      - `learnExclude` boolean, required: true when the post is excluded from learning: by the creator, or automatically when the Short went private or was deleted on YouTube, or because it is a Weekly Pop. Outcome capture skips it, so it gets no new measured windows.
      - `receiptUrl` string, uri, nullable, required
    - `totals` object, required
      - `posts` integer, required
      - `views48h` number, required
      - `views7d` number, required
      - `verifiedViews` number, required: Measured views: per post the 7-day window when measured, else 48h.
    - `estimatedPayoutCents` integer, nullable, required: totals.verifiedViews ÷ 1,000 × cpmCents, rounded; null without a CPM. An estimate — the marketplace's own view count governs payout.
    - `bundleUrl` string, uri, nullable, required: One token-protected link to the measured receipts; null when none is measured.
    - `publicUrl` string, uri, nullable, required: The token-protected public payout-report page.

## Other responses

- `401`: The API key did not authenticate. code=key_missing: no Authorization: Bearer epk_... header. code=key_invalid: the key is unknown or revoked. code=key_expired: the key passed its expiry; the user creates a new one in Dashboard → API.
- `402`: REST and MCP need the Pro or Scale plan. reason=subscription: the account has no active subscription (subscribe, or redeem an invite code). reason=plan: the account's plan doesn't include this (API and agent access need Pro or Scale).
- `403`: code=scope (also reason=scope): the API key is read-only and this is a write. code=suspended: the account is suspended. Endpoint-specific refusals document their own reason.
- `404`: Campaign not found for this account.
- `429`: Too many requests. code=rate_limited: the per-minute limit; wait Retry-After (60) seconds. code=quota_exhausted (with used, limit, resetsAt, retryable: false): the monthly allowance is used up; Retry-After is the seconds until resetsAt — tell the user rather than wait. code=queue_capacity (retryable: true): the render queue is full; retry after Retry-After (180).

---

[API](https://skmtc.dev/everpop/apis/everpop-api.md) · [All operations](https://skmtc.dev/everpop/apis/everpop-api/llms.txt) · [OpenAPI document](https://skmtc.dev/everpop/apis/everpop-api/revisions/1a9fb20867f5?raw)
