---
title: "Publish"
method: POST
path: "/{brand_id}/sites/{site_id}/agent-pages/publish"
tags: ["agent-pages"]
---

# Publish

`POST /{brand_id}/sites/{site_id}/agent-pages/publish`

## Request

- Base URL: `https://api.scrunchai.com/v1`
- URL: `https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/publish`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/scrunch/apis/scrunch-data-api/docs/:brand_id/sites/:site_id/agent-pages/publish/post.ts> (a function with typed inputs; its response is checked against the schema)

Make pages Agent Pages now, including pages your sitemap doesn't list. Each path is fetched from your live site, optimized and served once that finishes, usually within minutes. On a page-by-page setup each page is selected for Agent Pages and counts against your Agent Pages budget. On a page-by-page setup, the site serves only its Agent Pages set. With Site Optimization, a site with an empty set serves no Agent Pages; without it, a site serves every page until its first page is marked or published, so the first publish stops serving every page outside the set.

Returns one outcome per requested path. `queued` means the fetch was sent, not that the page is live: if your site doesn't serve the page (for example it answers 404), it stays selected but isn't served until a scheduled check finds it live (about every 30 days) or you send it again. If the send fails, the hourly scheduled check picks the page up, usually within an hour. `warnings` says when a queued page waits on your site: it was retired earlier, or recent checks saw it redirect.

A path the Agent Pages Unpublish API put on the Ignore List is published again; a dashboard Ignore List entry or path rule is never overridden (`excluded`). On a whole-site (legacy) setup the page is optimized without being added to any list. A path your CDN doesn't route to the Scrunch edge worker is stored but never served.

Limits: 100 paths per request; each path once every 5 minutes; per brand, 500 published paths per rolling hour and 5,000 per rolling 24 hours. These quotas are separate from Force Refresh's and Unpublish's.

Publish acts on the Agent Page only. Curated (Adaptive) content at the same path keeps being served, and the response doesn't report it.

## Path parameters

- `brand_id` integer, required: The unique identifier for the brand that owns the site.
- `site_id` string, required: The ULID of the registered site whose Agent Pages you are publishing.

## Request body

- AgentPagesPublishRequest
  - `paths` string[], required: Site-relative paths to publish, e.g. `/pricing`. 1 to 100 entries, each up to 2,048 characters. Full or protocol-relative URLs are rejected. Paths are trimmed and normalized (lowercased, trailing slash and query string dropped), and duplicates after normalization are merged. `/` is the homepage. The page is fetched with the first spelling sent, so a case-sensitive site gets the URL it expects.

## Response `200`

One outcome per requested path, in request order, plus the brand's remaining publish quota.

- AgentPagesPublishResponse
  - `results` AgentPagesPublishResult[], required: One entry per requested path, in request order (after duplicates are merged).
    - `path` string, required: The normalized path this outcome applies to. `/` is the homepage.
    - `outcome` 'queued' | 'already_published' | 'excluded' | 'over_budget' | 'invalid_path' | 'cooldown' | 'rate_limited', required: What happened to this path. `queued`: the page is an Agent Page now and its fetch was sent; it is served once the fetch and optimization finish, and a page your site doesn't serve (for example it answers 404) isn't served until a scheduled check finds it live (about every 30 days) or it is sent again. If the send fails, the hourly scheduled check picks the page up, usually within an hour. `already_published`: the page is already being served; nothing was fetched (use Force Refresh to pick up a change). `excluded`: a dashboard Ignore List entry or path rule blocks the path (on a whole-site setup with Priority List entries, so does being outside them); the API never overrides it. `over_budget`: the organization's Agent Pages budget is full (page-by-page setups only); in a batch, the first paths that fit are queued. `invalid_path`: not a web page (a file such as `.pdf`, `.json` or `.model.json`), or a path the page list can't store. `cooldown`: this path was published in the last 5 minutes; retry after `retry_after`. `rate_limited`: the brand's hourly or daily quota ran out partway through this batch.
    - `retry_after` string, date-time, nullable: For `cooldown`, when this path can be published again. Null otherwise.
    - `in_sitemap` boolean, nullable: For `queued` and `already_published` paths, whether the site's sitemap lists the page. Null for other outcomes.
    - `warnings` string[]: Why the page may not be served soon, or may be removed later. Empty when there is nothing to report. Possible entries, in this order: `Retired (<reason>), last checked <date>: it serves only once the origin answers 200.` (a `queued` page retired earlier; `<reason>` is `http_gone`, `sitemap_absent`, `non_html` or `admin_retired`; `<date>` is the last scheduled check, not the retirement date; either part is left out when unknown); `Recent checks saw this path redirect to <target>: it serves once a check sees the page answer for itself.` (a `queued` page that recent checks saw redirect; `<target>` reads `another URL` when none was recorded); `Not in the site's sitemap. Published as a manual Agent Page: it is not removed by the sitemap check, only by an origin 404 or redirect, or the unpublish API.` (a `queued` page with `in_sitemap: false`). A `queued` page the sitemap lists is managed by the sitemap, which can retire it once the sitemap drops it; an `already_published` page keeps how it was managed.
  - `quota` AgentPagesPublishQuotas, required: The brand's rolling publish windows, separate from the refresh and unpublish quotas. A path is queued only while both have room.
    - `hourly` AgentPagesRefreshQuota, required
      - `limit` integer, required: This window's cap.
      - `remaining` integer, required: Paths left in this window after this request.
      - `resets_at` string, date-time, nullable: When the oldest path counted in the window expires and frees a slot. Null when nothing has been used.
    - `daily` AgentPagesRefreshQuota, required
      - `limit` integer, required: This window's cap.
      - `remaining` integer, required: Paths left in this window after this request.
      - `resets_at` string, date-time, nullable: When the oldest path counted in the window expires and frees a slot. Null when nothing has been used.

## Other responses

- `404`: The site doesn't belong to the brand, or Agent Pages aren't enabled for the brand.
- `409`: Agent Pages aren't active on this site (or the site isn't serving through its CDN). Nothing was published and no quota was used.
- `422`: Validation Error
- `429`: The brand's hourly or daily publish quota is used up and nothing could be published, or another publish request for the same brand is still being processed.

## Changes

- **2026-11-03** `e37811b6bc07`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/scrunch/apis/scrunch-data-api/changes/:brand_id/sites/:site_id/agent-pages/publish/post.md)

---

[API](https://skmtc.dev/scrunch/apis/scrunch-data-api.md) - [All operations](https://skmtc.dev/scrunch/apis/scrunch-data-api/llms.txt) - [OpenAPI document](https://skmtc.dev/scrunch/apis/scrunch-data-api/revisions/e28a10a186bf?raw)
