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

# Manually add endpoints to the API base path

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>When a domain uses APIs hosted on the same domain without [API Discovery](/waap/api-discovery-and-protection/api-discovery) enabled, endpoints can be added manually to the API base path. This defines a communication path for WAAP to expect API requests and protect those endpoints.</p>

    <Info>
      This setting doesn't add API endpoints to the allowlist.
    </Info>

    <p>The following rules apply when entering a path:</p>

    * Paths are recursively allowed — `api/` allows `api/v1/*` and `api/v2/*`.
    * Regex/wildcard input is not accepted. Use `api/` instead of `api/*`.
    * Don't enter the protocol or domain. Use `api/` instead of `https://example.foobar.com/api/`. The domain is automatically added.
    * Paths are not case-sensitive. `API/` and `api/` are interchangeable.
    * Adding multiple APIs requires a separate entry for each one.

    ## Add endpoints to the base path

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

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/oiXMXoLAvnTxruCG/images/docs/waap/api-discovery-and-protection/domains-page.png?fit=max&auto=format&n=oiXMXoLAvnTxruCG&q=85&s=600ae6aa27fa9516f1f5e7b016bfd88a" alt="Domains page in the Customer Portal" width="1024" height="324" data-path="images/docs/waap/api-discovery-and-protection/domains-page.png" />
    </Frame>

    2. Select a domain from the list and click its name to open it. This opens the **Overview** page.
    3. In the sidebar, click **Settings**. On the page that opens, select the **API Base Path** tab.

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/oiXMXoLAvnTxruCG/images/docs/waap/api-discovery-and-protection/api-base-path-settings.png?fit=max&auto=format&n=oiXMXoLAvnTxruCG&q=85&s=771e9f7f34bceb582cbd89b1bf21c0ab" alt="API base path settings" width="1024" height="300" data-path="images/docs/waap/api-discovery-and-protection/api-base-path-settings.png" />
    </Frame>

    4. Either enable the **Set as API Domain** checkbox to treat the whole domain as an API or enter a specific API endpoint path into the **Host** input field.
    5. Click the **Add** button, and the endpoint will appear in the **Endpoint** table below.

    ## Remove endpoints from the base path

    1. Find the relevant endpoint and click the three-dot icon next to it.
    2. Select **Delete**.
    3. Confirm the action by clicking **Delete** again.

    <p>After the API base path is configured, CAPTCHA and JavaScript validation is disabled for added endpoints.</p>

    <p>The [DDoS protection](/waap/ddos-protection), [IP reputation](/waap/waap-policies/ip-reputation), and rate limitation features continue to protect those endpoints. Custom [WAAP rules](/waap/waap-rules/custom-rules) and [firewall rules](/waap/firewall/access-control#managing-allowed-and-blocked-ips) can also impact content delivery via API and potentially block users.</p>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>If a domain uses APIs hosted on the same domain and [API Discovery](/waap/api-discovery-and-protection/api-discovery) is not enabled, manually configure the API base path via the [Domains](/api-reference/waap#domains) settings endpoints to tell WAAP which paths to treat as API traffic. WAAP then disables CAPTCHA and JavaScript validation for those paths while keeping DDoS, IP reputation, and rate limiting active. Response examples include only the fields used in each step.</p>

    <Info>
      This setting doesn't add API paths to the allowlist.
    </Info>

    <p>The following rules apply when configuring API paths:</p>

    * Paths are recursively allowed — `api/` covers `api/v1/*` and `api/v2/*`.
    * Regex/wildcard input is not accepted. Use `api/` instead of `api/*`.
    * Don't include the protocol or domain. Use `api/` instead of `https://example.foobar.com/api/`.
    * API paths are not case-sensitive. `API/` and `api/` are interchangeable.

    <Warning>
      The `api_urls` field **replaces** the entire list on every update. Sending `{"api_urls": ["api/v3/"]}` erases all previously configured paths, leaving only `api/v3/`. Always retrieve the current list first and include all existing paths in the update.
    </Warning>

    <Info>
      An [API token](/account-settings/api-tokens) is required to make API calls. To get the domain ID, use [List domains](/waap/getting-started/manage-domains#list-domains).
    </Info>

    ```bash theme={null}
    export GCORE_API_KEY=your_api_key
    export DOMAIN_ID=your_domain_id
    ```

    ## View current configuration

    <p>Returns the current API base path settings, including the `is_api` flag and the configured `api_urls` list.</p>

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

        load_dotenv()
        client = Gcore()
        domain_id = int(os.environ["DOMAIN_ID"])

        settings = client.waap.domains.settings.get(domain_id)
        print("is_api:", settings.api.is_api)
        print("api_urls:", settings.api.api_urls)
        ```
      </Tab>

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

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

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

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()
            domainID, _ := strconv.ParseInt(os.Getenv("DOMAIN_ID"), 10, 64)

            settings, err := client.Waap.Domains.Settings.Get(ctx, domainID)
            if err != nil {
                panic(err.Error())
            }
            fmt.Println("is_api:", settings.API.IsAPI)
            fmt.Println("api_urls:", settings.API.APIURLs)
        }
        ```
      </Tab>

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

        <Accordion title="Response">
          ```json theme={null}
          {
            "api": {
              "is_api": false,
              "api_urls": ["api/v1/", "api/v2/"]
            }
            // ...
          }
          ```
        </Accordion>
      </Tab>
    </Tabs>

    ## Configure API paths

    <p>Add or remove API paths by sending the complete updated list. Always read the current list first, then modify it and send the result. Both operations use the same `PATCH /waap/v1/domains/{id}/settings` call. Returns HTTP 204 with no response body.</p>

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

        load_dotenv()
        client = Gcore()
        domain_id = int(os.environ["DOMAIN_ID"])

        settings = client.waap.domains.settings.get(domain_id)
        current = settings.api.api_urls or []

        # Add a path
        client.waap.domains.settings.update(
            domain_id,
            api={"api_urls": current + ["api/v3/"]},
        )

        # Remove a path
        # client.waap.domains.settings.update(
        #     domain_id,
        #     api={"api_urls": [u for u in current if u != "api/v2/"]},
        # )
        ```
      </Tab>

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

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

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

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()
            domainID, _ := strconv.ParseInt(os.Getenv("DOMAIN_ID"), 10, 64)

            settings, err := client.Waap.Domains.Settings.Get(ctx, domainID)
            if err != nil {
                panic(err.Error())
            }

            // Add a path
            err = client.Waap.Domains.Settings.Update(ctx, domainID, waap.DomainSettingUpdateParams{
                API: waap.DomainSettingUpdateParamsAPI{
                    APIURLs: append(settings.API.APIURLs, "api/v3/"),
                },
            })
            if err != nil {
                panic(err.Error())
            }
            fmt.Println("Updated.")

            // Remove a path: filter the list and send the result
            // pathToRemove := "api/v2/"
            // var updated []string
            // for _, u := range settings.API.APIURLs {
            //     if u != pathToRemove {
            //         updated = append(updated, u)
            //     }
            // }
            // client.Waap.Domains.Settings.Update(ctx, domainID, waap.DomainSettingUpdateParams{
            //     API: waap.DomainSettingUpdateParamsAPI{APIURLs: updated},
            // })
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        # Retrieve current paths first, then send the full updated list.
        # This example adds api/v3/ to an existing [api/v1/, api/v2/] list.
        curl -X PATCH "https://api.gcore.com/waap/v1/domains/${DOMAIN_ID}/settings" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{"api": {"api_urls": ["api/v1/", "api/v2/", "api/v3/"]}}'

        # To remove api/v2/, send the list without it:
        # -d '{"api": {"api_urls": ["api/v1/", "api/v3/"]}}'
        ```
      </Tab>
    </Tabs>

    ## Set domain as API

    <p>When `is_api` is enabled, WAAP treats all domain traffic as API requests and disables browser challenges globally — individual `api_urls` entries are ignored but remain stored and take effect again when `is_api` is set back to `false`. Returns HTTP 204 with no response body.</p>

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

        load_dotenv()
        client = Gcore()
        domain_id = int(os.environ["DOMAIN_ID"])

        client.waap.domains.settings.update(
            domain_id,
            api={"is_api": True},
        )
        ```
      </Tab>

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

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

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

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()
            domainID, _ := strconv.ParseInt(os.Getenv("DOMAIN_ID"), 10, 64)

            err := client.Waap.Domains.Settings.Update(ctx, domainID, waap.DomainSettingUpdateParams{
                API: waap.DomainSettingUpdateParamsAPI{
                    IsAPI: gcore.Bool(true),
                },
            })
            if err != nil {
                panic(err.Error())
            }
            fmt.Println("Updated.")
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X PATCH "https://api.gcore.com/waap/v1/domains/${DOMAIN_ID}/settings" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{"api": {"is_api": true}}'
        ```
      </Tab>
    </Tabs>
  </MethodSection>
</MethodSwitch>
