# Read the service catalog in pages

Gateway supports anonymous, read-only catalog pages. Reading a page never creates an order, signs a message, reserves a payment or authorizes spending. Existing checkout, payment choices and private delivery continue through their established routes.

## Website products: start here

Use `GET https://gatewayinformationgroup.com/api/catalog/v1/discovery` for product descriptions, displayed prices, browser checkout availability and wallet metadata. The default `view=compact` keeps the response concise; `view=wallet` also supplies the existing wallet request fields and any Insights counterpart. Inspect `purchase.available` and `checkout.available` separately. A public listing never authorizes a quote, signature or payment.

Supported query parameters are `q`, `id`, `category`, `limit`, `cursor` and `view`. The default limit is50, with supported limits1–100; the supported views are `compact` and `wallet`. An exact `id` cannot be combined with `q`, `category` or `cursor`. Use category IDs from current discovery. The older `wallet_available` filter belongs to the legacy complete-product route, not this paged endpoint.

Each response contains `kind: "gateway.catalog-page"`, `products`, `totalCount`, `revision`, `nextCursor`, `discoveryOnly: true` and `spendingAuthorized: false`. Follow the exact opaque cursor with the same filters until `nextCursor: null`. Never combine observations from different revisions. Read one product with `?id=actual-product-id` from the returned list; do not invent IDs. Complete execution schemas remain available through the original exact by-ID product route.

These product pages are bounded to512KiB. They are navigation/availability observations, not a reservation or proof that a later payment will be available. Use the returned current checkout URL or quote request only after the operator has approved the specific purchase. Guest checkout and optional verified-member benefits retain their existing requirements.

## Payment API service contracts

The following client methods and `/api/agent/v1/discovery` path use the payment API at `https://gateway-wallet-payments.jerryrnapier.workers.dev`, not the website product endpoint above. Its schema, parameters and bounds are deliberately different.

The current portable client checks `/healthz` for `discoveryVersion: "1.0.0"`. When supported, `discover()` reads complete service contracts in pages and returns the existing catalog object, including `services`, `paymentMethods`, policies and delivery information. Older servers continue through the existing `/api/agent/v1/catalog` route. A failed or changed paged response is reported explicitly; the client does not silently return a partial catalog or retry a payment.

```js
import {createGatewayClient} from './gateway-client.mjs';

const gateway = createGatewayClient();
const page = await gateway.discoverPage({
  kind: 'services',
  view: 'summary',
  limit: 100,
});
const contract = await gateway.describeService('website-quick-check');
```

Use `describeService(id)` to read one full service contract without downloading the entire inventory. For a selection, pass `ids: ['first-service-id', 'second-service-id']` to `discoverPage`; up to 100 distinct public IDs are supported per selection. Use actual IDs from discovery. Missing selected services are omitted; `describeService` reports `SERVICE_NOT_FOUND` when its requested service is absent.

The public endpoint is `GET /api/agent/v1/discovery`. It accepts:

| Parameter | Values |
| --- | --- |
| `kind` | `services` or `tools`; default `services` |
| `view` | `summary` or `full`; default `summary` |
| `limit` | 1–200; default 100; an upper bound on items, not a guaranteed page size |
| `ids` | Optional comma-separated selection of up to 100 distinct public IDs |
| `cursor` | The exact opaque `nextCursor` from the preceding response |

A summary item contains `id`, `version`, `price` and `contractSha256`. Full items retain the complete existing contracts. Each envelope includes `schemaVersion`, `kind: "gateway.discovery-page"`, `sourceKind`, `view`, `items`, `totalCount`, `revision`, `nextCursor`, `discoveryOnly: true` and `spendingAuthorized: false`. Service pages also include the current `paymentMethods` and `catalog` metadata. The hash identifies serialized contract bytes; it is not an endorsement or proof of payment.

To continue a selection, keep its `kind`, `view`, `limit` and `ids` unchanged and pass its `nextCursor`. Stop only at `nextCursor: null`; a shorter page may still have a continuation. A zero-item inventory has `totalCount: 0` and no continuation. Cursors are public observation markers, not credentials. Never put a private receipt capability or wallet secret in a URL, filter or cursor.

Pages are limited to 256,000 response bytes and adapt their item count to contract size. `discover()` follows pages sequentially with a 100 ms pause, rejects duplicate IDs and cursor cycles, and requires the revision, count, payment choices and metadata to remain consistent. It retains a 16 MiB aggregate transfer budget, a 60-second operation deadline and a 1,024-page ceiling. These are discovery resource budgets, not payment amount, purchase-count, payer or IP restrictions. For larger inventories, select individual contracts or process summary pages instead of retaining all full contracts at once.

Concurrent identical reads on one client are coalesced while in flight. Completed results are not cached as current availability. Public requests omit cookies and authorization headers, reject redirects and keep bounded response and stream deadlines. A `429` or `503` is returned without an automatic retry; its typed error includes `retryAfterMs`. Honor that delay before a later request. A stale cursor returns `409`; discard the partial observation and restart later. Do not combine pages from different observations.

Cached copies of an older client do not gain pagination automatically. Update the integration helper to use these methods. Existing clients and monolithic discovery routes remain available, but their existing response-size budgets still apply. Pagination improves discovery headroom; it does not establish unlimited service, compute or payment-provider capacity.
