Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .changeset/standardize-pagination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"adcontextprotocol": major
---

Standardize cursor-based pagination across all list operations.

### Breaking Changes

- **`list_creatives`**: Replace offset-based `limit`/`offset` with cursor-based `pagination` object
- **`tasks_list`**: Replace offset-based `limit`/`offset` with cursor-based `pagination` object
- **`list_property_lists`**: Move top-level `max_results`/`cursor` into nested `pagination` object
- **`get_property_list`**: Move top-level `max_results`/`cursor` into nested `pagination` object
- **`get_media_buy_artifacts`**: Move top-level `limit`/`cursor` into nested `pagination` object

### Non-Breaking Changes

- Add shared `pagination-request.json` and `pagination-response.json` schemas to `core/`
- Add optional `pagination` support to `list_accounts`, `get_products`, `list_creative_formats`, `list_content_standards`, and `get_signals`
- Update documentation for all affected operations

All list operations now use a consistent pattern: `pagination.max_results` + `pagination.cursor` in requests, `pagination.has_more` + `pagination.cursor` + optional `pagination.total_count` in responses.
1 change: 1 addition & 0 deletions docs/creative/task-reference/list_creative_formats.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ See [list_creative_formats (Sales Agent)](/docs/media-buy/task-reference/list_cr
| `min_height` | integer | No | Minimum height in pixels (inclusive) |
| `is_responsive` | boolean | No | Filter for responsive formats (adapt to container size) |
| `name_search` | string | No | Search formats by name (case-insensitive partial match) |
| `pagination` | object | No | Pagination: `max_results` (1-100, default 50) and `cursor` (opaque cursor from previous response) |

### Multi-Render Dimension Filtering

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ The buyer requests artifacts from the seller using the same media buy parameters
| `package_ids` | array | No | Filter to specific packages |
| `sampling` | object | No | Sampling parameters (defaults to media buy agreement) |
| `time_range` | object | No | Filter to specific time period |
| `limit` | integer | No | Maximum artifacts to return (default: 1000) |
| `cursor` | string | No | Pagination cursor for large result sets |
| `pagination` | object | No | Pagination parameters (see below) |

### Sampling Options

Expand All @@ -56,6 +55,15 @@ The buyer requests artifacts from the seller using the same media buy parameters
| `recent` | Most recent deliveries first |
| `failures_only` | Only artifacts that failed local evaluation |

### Pagination

Uses higher limits than standard pagination because artifact result sets can be very large.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `pagination.max_results` | integer | 1000 | Maximum artifacts per page (1-10,000) |
| `pagination.cursor` | string | - | Opaque cursor from a previous response |

## Response

**Schema**: [get-media-buy-artifacts-response.json](https://adcontextprotocol.org/schemas/v2/content-standards/get-media-buy-artifacts-response.json)
Expand Down Expand Up @@ -173,7 +181,7 @@ for i, result in enumerate(validation["results"]):
failures = seller_agent.get_media_buy_artifacts(
media_buy_id="mb_nike_reddit_q1",
sampling={"method": "failures_only"},
limit=100
pagination={"max_results": 100}
)

# Verify these were correctly flagged
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ List available content standards configurations.
| `countries` | array | No | Filter by ISO 3166-1 alpha-2 country codes (case-insensitive) |
| `channels` | array | No | Filter by channels |
| `languages` | array | No | Filter by ISO 639-1 or BCP 47 language tags (case-insensitive) |
| `pagination` | object | No | Pagination: `max_results` (1-100, default 50) and `cursor` (opaque cursor from previous response) |

## Response

Expand Down
18 changes: 10 additions & 8 deletions docs/governance/property/tasks/property_lists.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,9 @@ Retrieve a property list with optional resolution of filters.
"arguments": {
"list_id": "pl_abc123",
"resolve": true,
"max_results": 100
"pagination": {
"max_results": 1000
}
}
}
```
Expand All @@ -474,11 +476,10 @@ The response returns a compact list of **identifiers only** (not full property o
{ "type": "domain", "value": "ft.com" },
{ "type": "domain", "value": "theguardian.com" }
],
"total_count": 847,
"returned_count": 100,
"pagination": {
"has_more": true,
"cursor": "eyJvZmZzZXQiOjEwMH0="
"cursor": "eyJvZmZzZXQiOjEwMH0=",
"total_count": 847
},
"resolved_at": "2026-01-03T17:15:00Z",
"cache_valid_until": "2026-01-04T17:15:00Z"
Expand Down Expand Up @@ -545,7 +546,9 @@ List all property lists accessible to the authenticated principal.
"tool": "list_property_lists",
"arguments": {
"name_contains": "UK",
"max_results": 50
"pagination": {
"max_results": 50
}
}
}
```
Expand Down Expand Up @@ -574,10 +577,9 @@ List all property lists accessible to the authenticated principal.
"property_count": 156
}
],
"total_count": 3,
"returned_count": 3,
"pagination": {
"has_more": false
"has_more": false,
"total_count": 3
}
}
```
Expand Down
18 changes: 18 additions & 0 deletions docs/media-buy/task-reference/get_products.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ asyncio.run(discover_with_filters())
| `brand_manifest` | BrandManifest \| string | No | Brand information (inline object or URL). See [Brand Manifest](/docs/creative/brand-manifest) |
| `filters` | Filters | No | Structured filters (see below) |
| `property_list` | PropertyListRef | No | [AdCP 3.0] Reference to a property list for filtering. See [Property Lists](/docs/governance/property/tasks/property_lists) |
| `pagination` | PaginationRequest | No | Cursor-based pagination for large product catalogs (see below) |

### Filters Object

Expand Down Expand Up @@ -188,6 +189,23 @@ Publishers may return proposals alongside products - structured media plans with
| `brief_alignment` | string | How this proposal addresses the campaign brief |
| `expires_at` | string | ISO 8601 timestamp when this proposal expires |

### Pagination

For large product catalogs, use cursor-based pagination:

| Request Parameter | Type | Description |
|---|---|---|
| `pagination.max_results` | integer | Maximum products per page (1-100, default: 50) |
| `pagination.cursor` | string | Cursor from previous response for next page |

| Response Field | Type | Description |
|---|---|---|
| `pagination.has_more` | boolean | Whether more products are available |
| `pagination.cursor` | string | Cursor to pass for the next page |
| `pagination.total_count` | integer | Total matching products (optional, not all backends support this) |

Pagination is optional. When omitted, the server returns all results (or a server-chosen default page). When the response includes `pagination.has_more: true`, pass `pagination.cursor` in the next request to get the next page.

### Response Metadata

| Field | Type | Description |
Expand Down
26 changes: 12 additions & 14 deletions docs/media-buy/task-reference/list_creatives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ Sort results by various fields with ascending or descending order:

## Pagination

Control result set size and navigation:
Control result set size with cursor-based pagination:

```json
{
"pagination": {
"limit": 50, // Max results per page (1-100, default: 50)
"offset": 0 // Results to skip (default: 0)
"max_results": 50, // Max results per page (1-100, default: 50)
"cursor": "eyJjcmVhdGVkX2RhdGUiOi4uLn0" // Cursor from previous response (omit for first page)
}
}
```
Expand All @@ -162,11 +162,9 @@ The response provides comprehensive creative data with optional enrichment:
"filters_applied": ["format=video", "status=approved"]
},
"pagination": {
"limit": 10,
"offset": 0,
"has_more": true,
"total_pages": 3,
"current_page": 1
"cursor": "eyJjcmVhdGVkX2RhdGUiOiIyMDI0LTAxLTE1VDEwOjMwOjAwWiJ9",
"total_count": 25
},
"creatives": [
{
Expand Down Expand Up @@ -216,7 +214,7 @@ List all approved video creatives:
"direction": "desc"
},
"pagination": {
"limit": 20
"max_results": 20
}
}
```
Expand Down Expand Up @@ -255,7 +253,7 @@ Get creatives ready for assignment to new campaigns:
"direction": "desc"
},
"pagination": {
"limit": 50
"max_results": 50
}
}
```
Expand Down Expand Up @@ -347,7 +345,7 @@ Analyze creative uploads over a specific quarter:
"direction": "asc"
},
"pagination": {
"limit": 100
"max_results": 100
}
}
```
Expand Down Expand Up @@ -502,10 +500,10 @@ For queries returning very large result sets:
- Use format and status filters to reduce result sets
- Combine date ranges with other filters for efficiency

### 2. Paginate Appropriately
### 2. Paginate Appropriately
- Avoid very large page sizes (>100) which may timeout
- Use offset-based pagination for consistent results
- Consider cursor-based pagination for very large libraries
- Use the `cursor` from the previous response to fetch the next page
- Cursor-based pagination handles data changes between requests

### 3. Field Selection
- Request only needed fields using the `fields` parameter
Expand Down Expand Up @@ -537,7 +535,7 @@ const response = await adcp.list_creatives({
},
sort: { field: "performance_score", direction: "desc" },
include_performance: true,
pagination: { limit: 10 }
pagination: { max_results: 10 }
});
```

Expand Down
1 change: 1 addition & 0 deletions docs/signals/tasks/get_signals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The `get_signals` task returns both signal metadata and real-time deployment sta
| `deliver_to` | DeliverTo | Yes | Deployment targets where signals need to be activated (see Deliver To Object below) |
| `filters` | Filters | No | Filters to refine results (see Filters Object below) |
| `max_results` | number | No | Maximum number of results to return |
| `pagination` | object | No | Pagination: `cursor` (opaque cursor from previous response) for paging through large result sets |

### Deliver To Object

Expand Down
3 changes: 3 additions & 0 deletions static/schemas/source/account/list-accounts-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"default": "active",
"description": "Filter accounts by status"
},
"pagination": {
"$ref": "/schemas/core/pagination-request.json"
},
"context": {
"$ref": "/schemas/core/context.json"
},
Expand Down
9 changes: 8 additions & 1 deletion static/schemas/source/account/list-accounts-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"$ref": "/schemas/core/error.json"
}
},
"pagination": {
"$ref": "/schemas/core/pagination-response.json"
},
"context": {
"$ref": "/schemas/core/context.json"
},
Expand Down Expand Up @@ -53,7 +56,11 @@
"advertiser": "Publicis Media",
"status": "active"
}
]
],
"pagination": {
"has_more": false,
"total_count": 3
}
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,23 @@
}
}
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 10000,
"default": 1000,
"description": "Maximum artifacts to return per request"
},
"cursor": {
"type": "string",
"description": "Pagination cursor for fetching subsequent pages"
"pagination": {
"type": "object",
"description": "Pagination parameters. Uses higher limits than standard pagination because artifact result sets can be very large.",
"properties": {
"max_results": {
"type": "integer",
"minimum": 1,
"maximum": 10000,
"default": 1000,
"description": "Maximum number of artifacts to return per page"
},
"cursor": {
"type": "string",
"description": "Opaque cursor from a previous response to fetch the next page"
}
},
"additionalProperties": false
},
"context": {
"$ref": "/schemas/core/context.json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,7 @@
}
},
"pagination": {
"type": "object",
"description": "Pagination information for large result sets",
"properties": {
"cursor": {
"type": "string",
"description": "Cursor for fetching the next page"
},
"has_more": {
"type": "boolean",
"description": "Whether more results are available"
}
}
"$ref": "/schemas/core/pagination-response.json"
},
"errors": {
"not": {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
"items": { "type": "string" },
"description": "Filter by ISO 3166-1 alpha-2 country codes"
},
"pagination": {
"$ref": "/schemas/core/pagination-request.json"
},
"context": {
"$ref": "/schemas/core/context.json"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"not": {},
"description": "Field must not be present in success response"
},
"pagination": {
"$ref": "/schemas/core/pagination-response.json"
},
"context": {
"$ref": "/schemas/core/context.json"
},
Expand Down
21 changes: 21 additions & 0 deletions static/schemas/source/core/pagination-request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "/schemas/core/pagination-request.json",
"title": "Pagination Request",
"description": "Standard cursor-based pagination parameters for list operations",
"type": "object",
"properties": {
"max_results": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50,
"description": "Maximum number of items to return per page"
},
"cursor": {
"type": "string",
"description": "Opaque cursor from a previous response to fetch the next page"
}
},
"additionalProperties": false
}
24 changes: 24 additions & 0 deletions static/schemas/source/core/pagination-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "/schemas/core/pagination-response.json",
"title": "Pagination Response",
"description": "Standard cursor-based pagination metadata for list responses",
"type": "object",
"properties": {
"has_more": {
"type": "boolean",
"description": "Whether more results are available beyond this page"
},
"cursor": {
"type": "string",
"description": "Opaque cursor to pass in the next request to fetch the next page. Only present when has_more is true."
},
"total_count": {
"type": "integer",
"minimum": 0,
"description": "Total number of items matching the query across all pages. Optional because not all backends can efficiently compute this."
}
},
"required": ["has_more"],
"additionalProperties": false
}
Loading