# Get paid ad

Read one stored paid-ad observation with its matched listing and the ads around it.

## Contract status

Preview contract: these routes and tools are implemented in the shared contract, but the public host, customer API access and OAuth flow have not been deployment verified.

## Endpoint: GET /v1/paid-ads/{platform}/{archiveId}

- Method: `GET`
- Path: `/v1/paid-ads/{platform}/{archiveId}`
- Authentication: Bearer API credential or OAuth access token
- Required scope: `context:read`
- MCP tool: `get_paid_ad`

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | meta | tiktok | yes | Advertising platform. |
| `archiveId` | path | string, 1–255 | yes | Provider archive id. |

## Known errors

- 400 invalid_request for an invalid filter, identity or limit.
- 401 authentication_required for a missing or invalid credential.
- 402 subscription_required when access is not entitled.
- 403 authorization_required for a missing scope or unavailable preview access.
- 404 not_found when the record is outside the accessible catalogue.
- 429 rate_limited; honor Retry-After when present.

## Request

Identify the ad with the platform and archive id carried in its canonicalKey. This read returns stored observations and never collects new ads.

```
curl --get 'https://api.peekpanda.com/v1/paid-ads/meta/111222333' \
  --header "Authorization: Bearer $PEEKPANDA_TOKEN" \
  --header 'x-genviral-tenancy: personal'
```

## Response

item is the stored observation. product is the matched iOS listing, or null when the ad carries no verified store link. sameAppAds holds up to six further stored ads for that listing and otherAppAds up to six for other apps. transcript and analysis are null until they have been collected. The route answers 404 when no stored ad matches the identity.

```
{
  "item": {
    "id": "33333333-3333-4333-8333-333333333333",
    "canonicalKey": "paid:meta:111222333",
    "source": "paid",
    "platform": "meta",
    "archiveId": "111222333",
    "advertiser": {
      "externalId": "444555666",
      "name": "Example Advertiser"
    },
    "status": "active",
    "startedAt": "2026-08-01T00:00:00.000Z",
    "endedAt": null,
    "discoveredAt": "2026-09-06T00:00:00.000Z",
    "sourceUrl": "https://www.facebook.com/ads/library?id=111222333",
    "creative": {
      "format": "video",
      "hook": "Turn saved recipes into a grocery list",
      "body": "Turn saved recipes into a grocery list.",
      "title": "Example Meal Planner",
      "description": null,
      "ctaText": "Download",
      "imageUrls": [
        "https://cdn.example.com/ad.jpg"
      ],
      "videoUrls": [
        "https://cdn.example.com/ad.mp4"
      ],
      "units": []
    },
    "productLink": {
      "kind": "official_domain",
      "name": "Example Meal Planner",
      "url": "https://example.com",
      "externalId": null,
      "confidence": "unresolved"
    },
    "productIconUrl": null,
    "performance": {
      "kind": "unavailable"
    },
    "saved": false
  },
  "product": null,
  "sameAppAds": [],
  "otherAppAds": [],
  "transcript": null,
  "analysis": null
}

```

## Source

Stored Meta/TikTok ad-library observations (scrapecreators or direct Meta). Not Apple. No spend field.

## Refresh

Paid-ad ingestion is a separate operator path; this GET is a stored read. Save/remove are account bookmarks.
