# Browse paid-ad shelves

Read paid ads as per-advertiser shelves, plus shelves for newly launched and long-running creatives.

## 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/rails

- Method: `GET`
- Path: `/v1/paid-ads/rails`
- Authentication: Bearer API credential or OAuth access token
- Required scope: `context:read`
- MCP tool: `get_ads`
- MCP action: `rails`

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `category` | query | category | no | Limit shelves to one category. |
| `platform` | query | meta | tiktok | no | Advertising platform. |
| `search` | query | string, max 120 | no | Advertiser or creative text. |
| `sort` | query | most_tested | longest_running | most_live | recently_tracked | no | Order of the advertiser shelves. Defaults to most_tested. |
| `railSize` | query | integer, 4-20 | no | Creatives on each shelf. Defaults to 10. |
| `advertiserLimit` | query | integer, 1-20 | no | Advertiser shelves to return. Defaults to 8. |

## 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

Every filter is optional. This read serves stored ads and does not collect new ones.

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

## MCP request

Call get_ads with action rails. Path fields go in params, filters in query, and a write body in body.

```
{
  "name": "get_ads",
  "arguments": {
    "request": {
      "action": "rails"
    }
  }
}

```

## Response

rails is empty when nothing is stored. totals uses the same counts as the ranking read.

```
{
  "generatedAt": "2026-09-06T00:00:00.000Z",
  "rails": [],
  "totals": {
    "ads": 0,
    "liveAds": 0,
    "advertisers": 0,
    "liveAdvertisers": 0,
    "newAdsLast7Days": 0,
    "advertisersShippingLast7Days": 0,
    "medianRunDays": null,
    "longestRunDays": null,
    "liveBeyond60Days": 0,
    "reachDisclosedAds": 0,
    "unlinkedAds": 0
  }
}

```

## Source

Stored paid-ad observations. Rankings count creatives and how long they stay live. There is no spend or impression field.

## Refresh

These reads do not collect new ads.
