> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage custom response pages

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).map(c => {
    if (!c || !c.props) return null;
    if (c.props.id) return c;
    const inner = c.props.children;
    if (inner && inner.props && inner.props.id) return inner;
    return null;
  }).filter(Boolean);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
    window.dispatchEvent(new Event("scroll"));
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    <p>There are two ways to access custom response pages: at the **domain** level and at the **account** level. The key difference is that at the domain level, you can only switch between page sets, and it's not possible to add, modify, or delete pages there.</p>

    <Info>
      **Info**

      For guidelines on how to create custom response pages, check out [Create custom response pages](/waap/response-pages/create-custom-response-pages) guide.
    </Info>

    ## Manage custom response pages at the account level

    <p>Custom response pages that are available at the account level relate to all domains in your account. This means that you can modify pages or page sets, and the changes will be inherited by all domains where those pages are active.</p>

    <p>To view page sets, open the **WAAP** page and navigate to **Response Pages**. You'll be directed to the page with all relevant settings.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/bDhdzFkD6lztVu55/images/docs/waap/response-pages/response-pages-account-level.png?fit=max&auto=format&n=bDhdzFkD6lztVu55&q=85&s=505225b116918a92b7ba104a3448d737" alt="Response pages functionality in the Customer Portal" width="1603" height="881" data-path="images/docs/waap/response-pages/response-pages-account-level.png" />
    </Frame>

    <p>Here you can view [default response pages](/waap/response-pages#types-of-response-pages) as well as add, customize, or delete your own custom page sets, which are based on the default ones.</p>

    <p>Each custom response page can have one of the following statuses:</p>

    * **Active** : A page appears on your domain and is visible to users.

    * **Inactive** : A page is created but not publicly available.

    <p>A page set statuses can be:</p>

    * **Unpublished** : A page set can get this status after creation. After a short period, it should change to **Published**.

    * **Published** : A page set is ready to use. This means that all pages inside it are in the **Active** status.

    ## Manage custom response pages at the domain level

    <p>A domain can have only one active page set at a time.</p>

    <p>To view or change page sets:</p>

    <p>1. In the [Gcore Customer Portal](https://portal.gcore.com/accounts/reports/dashboard), navigate to **WAAP** > **Domains**.</p>

    <p>2. Find the needed domain and click its name to open it. You'll be directed to the **Overview** page.</p>

    <p>3. In the sidebar, click **Response Pages**. On this page, you'll see all response pages that are currently applied to your domain.</p>

    <p>4. (Optional) To change a page set, click **Set as active** next to the desired page set.</p>

    <Info>
      **Info**

      If your domain has no active page sets, the [default response pages](/waap/response-pages#types-of-response-pages) will be used instead.
    </Info>

    ## Update a page set

    <p>You can apply the following actions to the whole set with your custom response pages: select domains where this page set will be applied, add a new page to the page set, edit one of the existing pages, or delete the page set altogether.</p>

    <p>Updating custom response pages is only possible on the account level.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/bDhdzFkD6lztVu55/images/docs/waap/response-pages/update-page-set.png?fit=max&auto=format&n=bDhdzFkD6lztVu55&q=85&s=81297a580223d2a0cf798cb1440b706f" alt="Update page set on the account level" width="1321" height="862" data-path="images/docs/waap/response-pages/update-page-set.png" />
    </Frame>

    <p>The process of adding, editing, and removing pages in an existing set are the same as for individual pages:</p>

    * [Create custom response pages](/waap/response-pages/create-custom-response-pages)

    * [Update custom response pages](/waap/response-pages/manage-custom-response-pages#update-custom-response-pages)

    ### Add a page set to domains

    <Info>
      **Info**

      If you don't add customized pages to a domain, one of the [default response pages](/waap/response-pages#types-of-response-pages) will be used instead.
    </Info>

    <p>You can apply custom response pages to any domain of your choice. To add a page to a domain:</p>

    <p>1. In the [Gcore Customer Portal](https://portal.gcore.com/accounts/reports/dashboard), navigate to **WAAP** > **Response Pages**. Here you'll see all default and custom response pages.</p>

    <p>2. Find the page set that you want to modify, and click three-dot icon next to it.</p>

    <p>3. Choose **Select domains**. Click the checkbox next to all domains you would like to apply this page set. If the list is extensive, search for desired domains.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/bDhdzFkD6lztVu55/images/docs/waap/response-pages/add-page-set-to-domain.png?fit=max&auto=format&n=bDhdzFkD6lztVu55&q=85&s=7b088a1b9899cef5f379bee835df560e" alt="Add domains to a page set on the account level" width="1289" height="256" data-path="images/docs/waap/response-pages/add-page-set-to-domain.png" />
    </Frame>

    <p>4. Click **Save selection**.</p>

    <p>5. Confirm your action by clicking **Confirm**. Any pages used on the domain will be replaced by this new page set.</p>

    ### Update custom response pages

    <p>You can modify various aspects of custom response pages, such as images, tab titles, or error messages. However, changing the page type itself is not possible. For example, you can't convert a Captcha page into a Block page. If you need a different page type, you must create a new response page of the desired type.</p>

    <Info>
      **Info**

      If you modify a created page in a page set, the changes will be reflected on all domains using that set.
    </Info>

    <p>To update an existing page:</p>

    <p>1. In the [Gcore Customer Portal](https://portal.gcore.com/accounts/reports/dashboard), navigate to **WAAP** > **Response Pages**.</p>

    <p>2. Find the page set that you want to modify and click the three-dot icon next to it.</p>

    <p>3. Select **Edit page**.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/bDhdzFkD6lztVu55/images/docs/waap/response-pages/edit-page.png?fit=max&auto=format&n=bDhdzFkD6lztVu55&q=85&s=91f55ed9dc0dd9ddc49da26032a958ad" alt="Edit page button in the page set settings" width="1920" height="945" data-path="images/docs/waap/response-pages/edit-page.png" />
    </Frame>

    ## Delete custom response pages

    <p>After you delete a page set, any domains that are currently using it will automatically revert back to the default response ages. You can't restore deleted pages.</p>

    <p>To delete a page:</p>

    <p>1. In the [Gcore Customer Portal](https://portal.gcore.com/accounts/reports/dashboard), navigate to **WAAP** > **Response Pages**.</p>

    <p>2. Find the page set that you want to modify and click the three-dot icon next to it.</p>

    <p>3. Select **Delete**.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/bDhdzFkD6lztVu55/images/docs/waap/response-pages/delete-page.png?fit=max&auto=format&n=bDhdzFkD6lztVu55&q=85&s=d129e8aa1081f590340420ef12f17789" alt="Delete page button in the page set settings" width="1920" height="945" data-path="images/docs/waap/response-pages/delete-page.png" />
    </Frame>

    <p>4. Click **Delete**.</p>

    <p>Your page has been successfully removed and will no longer be displayed on any domains where it was previously used.</p>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>The [Custom Page Sets](/api-reference/waap#custom-page-sets) endpoints support partial updates — a single <code>PATCH /waap/v1/custom-page-sets/{set_id}</code> call can change the name, page content, domain assignments, or any combination. Response examples include only the fields used in each step.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required. To assign a page set to a domain, retrieve the WAAP domain ID via <code>GET /waap/v1/domains</code>.
    </Info>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export WAAP_DOMAIN_ID="{YOUR_DOMAIN_ID}"
    export PAGE_SET_ID="{YOUR_PAGE_SET_ID}"
    ```

    ## List page sets

    <p>Returns all page sets for the account, including their IDs, names, domain assignments, and page configurations. Use the `id` from the response in subsequent update and delete calls.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import gcore
        import os

        client = gcore.Gcore(api_key=os.environ["GCORE_API_KEY"])

        page_sets = client.waap.custom_page_sets.list()
        for ps in page_sets:
            print(f"id={ps.id} name={ps.name!r}")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/option"
            "github.com/G-Core/gcore-go/waap"
        )

        func main() {
            client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))

            page, err := client.Waap.CustomPageSets.List(context.Background(), waap.CustomPageSetListParams{})
            if err != nil {
                panic(err)
            }
            for _, ps := range page.Results {
                fmt.Printf("id=%d name=%s\n", ps.ID, ps.Name)
            }
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X GET "https://api.gcore.com/waap/v1/custom-page-sets" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Response:

        ```json theme={null}
        {
          "limit": 100,
          "offset": 0,
          "count": 1,
          "results": [
            {
              "id": 3321,
              "name": "My custom pages",
              "domains": [12345],
              "block": {
                "enabled": true,
                "header": "Access Denied",
                "title": "You have been blocked",
                "text": "Your request was blocked by the security policy.",
                "logo": null
              },
              "block_csrf": null,
              "captcha": null,
              "cookie_disabled": null,
              "handshake": null,
              "javascript_disabled": null
              // ...
            }
            // ...
          ]
        }
        ```
      </Tab>
    </Tabs>

    ## Update page content

    <p>Update one or more pages within a page set. Returns HTTP 204 with no response body.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import gcore
        import os

        client = gcore.Gcore(api_key=os.environ["GCORE_API_KEY"])
        set_id = int(os.environ["PAGE_SET_ID"])

        client.waap.custom_page_sets.update(
            set_id,
            block={
                "enabled": True,
                "header": "Access Denied",
                "title": "You have been blocked",
                "text": "Your request was blocked by the security policy. Contact support if this is a mistake.",
            },
        )
        print("Updated.")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/option"
            "github.com/G-Core/gcore-go/waap"
        )

        func main() {
            client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
            setID, _ := strconv.ParseInt(os.Getenv("PAGE_SET_ID"), 10, 64)

            err := client.Waap.CustomPageSets.Update(context.Background(), setID, waap.CustomPageSetUpdateParams{
                Block: waap.CustomPageSetUpdateParamsBlock{
                    Enabled: true,
                    Header:  gcore.String("Access Denied"),
                    Title:   gcore.String("You have been blocked"),
                    Text:    gcore.String("Your request was blocked by the security policy. Contact support if this is a mistake."),
                },
            })
            if err != nil {
                panic(err)
            }
            fmt.Println("Updated.")
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X PATCH "https://api.gcore.com/waap/v1/custom-page-sets/${PAGE_SET_ID}" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{
            "block": {
              "enabled": true,
              "header": "Access Denied",
              "title": "You have been blocked",
              "text": "Your request was blocked by the security policy. Contact support if this is a mistake."
            }
          }'
        ```

        Returns HTTP 204 with no response body.
      </Tab>
    </Tabs>

    ## Assign to domains

    <p>Controls which domains display a page set. The provided list replaces all existing assignments — to add a domain, include all currently assigned domains plus the new one. Pass an empty list to remove all assignments. A domain can have only one active page set at a time.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import gcore
        import os

        client = gcore.Gcore(api_key=os.environ["GCORE_API_KEY"])
        set_id = int(os.environ["PAGE_SET_ID"])
        domain_id = int(os.environ["WAAP_DOMAIN_ID"])

        # Assign to a domain
        client.waap.custom_page_sets.update(set_id, domains=[domain_id])
        print(f"Assigned page set {set_id} to domain {domain_id}.")

        # Remove all domain assignments
        # client.waap.custom_page_sets.update(set_id, domains=[])
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"

            "github.com/G-Core/gcore-go/option"
            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/waap"
        )

        func main() {
            client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
            setID, _ := strconv.ParseInt(os.Getenv("PAGE_SET_ID"), 10, 64)
            domainID, _ := strconv.ParseInt(os.Getenv("WAAP_DOMAIN_ID"), 10, 64)

            // Assign to a domain
            err := client.Waap.CustomPageSets.Update(context.Background(), setID, waap.CustomPageSetUpdateParams{
                Domains: []int64{domainID},
            })
            if err != nil {
                panic(err)
            }
            fmt.Printf("Assigned page set %d to domain %d.\n", setID, domainID)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        # Assign to a domain
        curl -X PATCH "https://api.gcore.com/waap/v1/custom-page-sets/${PAGE_SET_ID}" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{"domains": ['"${WAAP_DOMAIN_ID}"']}'

        # Remove all domain assignments
        # curl -X PATCH "https://api.gcore.com/waap/v1/custom-page-sets/${PAGE_SET_ID}" \
        #   -H "Authorization: APIKey ${GCORE_API_KEY}" \
        #   -H "Content-Type: application/json" \
        #   -d '{"domains": []}'
        ```

        Returns HTTP 204 with no response body.
      </Tab>
    </Tabs>

    ## Delete a page set

    <p>Deletes a page set permanently. Domains that were using the set revert to the default Gcore response pages. Returns HTTP 204 with no response body.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import gcore
        import os

        client = gcore.Gcore(api_key=os.environ["GCORE_API_KEY"])
        set_id = int(os.environ["PAGE_SET_ID"])

        client.waap.custom_page_sets.delete(set_id)
        print(f"Deleted page set {set_id}.")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"

            "github.com/G-Core/gcore-go/option"
            gcore "github.com/G-Core/gcore-go"
        )

        func main() {
            client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
            setID, _ := strconv.ParseInt(os.Getenv("PAGE_SET_ID"), 10, 64)

            err := client.Waap.CustomPageSets.Delete(context.Background(), setID)
            if err != nil {
                panic(err)
            }
            fmt.Printf("Deleted page set %d.\n", setID)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X DELETE "https://api.gcore.com/waap/v1/custom-page-sets/${PAGE_SET_ID}" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Returns HTTP 204 with no response body.
      </Tab>
    </Tabs>
  </MethodSection>
</MethodSwitch>
