curl --request POST \
--url https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"paths": [
"<string>"
],
"immediate": false
}
'import requests
url = "https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish"
payload = {
"paths": ["<string>"],
"immediate": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({paths: ['<string>'], immediate: false})
};
fetch('https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'paths' => [
'<string>'
],
'immediate' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish"
payload := strings.NewReader("{\n \"paths\": [\n \"<string>\"\n ],\n \"immediate\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"paths\": [\n \"<string>\"\n ],\n \"immediate\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"paths\": [\n \"<string>\"\n ],\n \"immediate\": false\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"path": "/pricing",
"outcome": "unpublished",
"retry_after": null,
"edge": "deleted"
},
{
"path": "/old-campaign",
"outcome": "already_unpublished",
"retry_after": null,
"edge": null
},
{
"path": "/careers",
"outcome": "not_found",
"retry_after": null,
"edge": null
}
],
"quota": {
"hourly": {
"limit": 100,
"remaining": 99,
"resets_at": "2026-10-28T15:02:41Z"
},
"daily": {
"limit": 1000,
"remaining": 987,
"resets_at": "2026-10-29T09:15:03Z"
}
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Unpublish
Stop serving Agent Pages now. Each path is added to the site’s Ignore List, so it stays unpublished through later crawls, sitemap checks and page selections, and its copy is removed from the edge within minutes, or before the response with immediate: true.
Returns one outcome per requested path. A path that has nothing to remove doesn’t cause an error.
Limits: 100 paths per request; each path once every 5 minutes; per brand, 100 unpublished paths per rolling hour and 1,000 per rolling 24 hours. These quotas are separate from Force Refresh’s.
Unpublish acts on the Agent Page only. Curated (Adaptive) content at the same path keeps being served, and the response doesn’t report it; remove it with the AXP Unpublish API.
curl --request POST \
--url https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"paths": [
"<string>"
],
"immediate": false
}
'import requests
url = "https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish"
payload = {
"paths": ["<string>"],
"immediate": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({paths: ['<string>'], immediate: false})
};
fetch('https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'paths' => [
'<string>'
],
'immediate' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish"
payload := strings.NewReader("{\n \"paths\": [\n \"<string>\"\n ],\n \"immediate\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"paths\": [\n \"<string>\"\n ],\n \"immediate\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrunchai.com/v1/{brand_id}/sites/{site_id}/agent-pages/unpublish")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"paths\": [\n \"<string>\"\n ],\n \"immediate\": false\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"path": "/pricing",
"outcome": "unpublished",
"retry_after": null,
"edge": "deleted"
},
{
"path": "/old-campaign",
"outcome": "already_unpublished",
"retry_after": null,
"edge": null
},
{
"path": "/careers",
"outcome": "not_found",
"retry_after": null,
"edge": null
}
],
"quota": {
"hourly": {
"limit": 100,
"remaining": 99,
"resets_at": "2026-10-28T15:02:41Z"
},
"daily": {
"limit": 1000,
"remaining": 987,
"resets_at": "2026-10-29T09:15:03Z"
}
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
The unique identifier for the brand that owns the site.
The ULID of the registered site whose Agent Pages you are unpublishing.
Body
Site-relative paths to unpublish, 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.
1 - 100 elementsDelete the edge copies before responding, instead of within minutes. Every path whose copy was still at the edge then reports edge, whatever its outcome, so a retry also cleans up a copy an earlier call left behind. A CDN cache in front of your site can still serve a copy it already holds until that copy expires.
Response
One outcome per requested path, in request order, plus the brand's remaining unpublish quota.