> ## 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.

# Create and manage a router

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>Cloud Router connects subnets to external networks and controls traffic between them using static routes. The list of routers is available in networking settings, on the **Routers** page.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/gc7JxAc22A27n3nY/images/docs/cloud/networking/create-and-manage-a-router/create-router-button.png?fit=max&auto=format&n=gc7JxAc22A27n3nY&q=85&s=a944daee7b2387b0537879003198cd7c" alt="Create router button highlighted" width="1400" height="430" data-path="images/docs/cloud/networking/create-and-manage-a-router/create-router-button.png" />
    </Frame>

    ## Create a router

    <p>A router can be created in two ways:</p>

    * Manually on the **Routers** page as documented in the following section.

    * When a [network](/cloud/networking/create-and-manage-a-network) is created, a new router is automatically provisioned to enable traffic routing. Automatically created routers support the same configuration options as manually created routers.

    ### Create a router manually

    1. In the [Gcore Customer Portal](https://portal.gcore.com), navigate to **Cloud** > **Networking**.

    2. Go to the **Routers** page and click **Create router**.

    3. Select the network and subnetwork to configure routing. To add multiple subnetworks, click **Add Subnet**.

    <Frame>
      <img src="https://mintcdn.com/gcore/gc7JxAc22A27n3nY/images/docs/cloud/networking/create-and-manage-a-router/create-router-form.png?fit=max&auto=format&n=gc7JxAc22A27n3nY&q=85&s=400c7de9ab8c6d0e129c69dbea149709" alt="Create router form" width="1400" height="900" data-path="images/docs/cloud/networking/create-and-manage-a-router/create-router-form.png" />
    </Frame>

    4. (Optional) Select the **Enable SNAT** checkbox to enable access to the external network. A separate public IP address is announced for a router with external network access. This setting can be changed at any time after the router is created.

    5. Specify the routing scheme in the **Static Routes** section. Provide the destination prefix and the address of the next hop. To add the next route, click the **Add Route** button.

    <Frame>
      <img src="https://mintcdn.com/gcore/c-GSw73gRYekqiTo/images/docs/cloud/networking/create-and-manage-a-router/create-router-snat-static-routes.png?fit=max&auto=format&n=c-GSw73gRYekqiTo&q=85&s=12f9f501aaae9bb91b1c71599647ce02" alt="SNAT and static routes configuration" width="3928" height="1372" data-path="images/docs/cloud/networking/create-and-manage-a-router/create-router-snat-static-routes.png" />
    </Frame>

    6. Enter a name for the router and click **Create Router** to save the configuration.

    <Frame>
      <img src="https://mintcdn.com/gcore/c-GSw73gRYekqiTo/images/docs/cloud/networking/create-and-manage-a-router/create-router-name.png?fit=max&auto=format&n=c-GSw73gRYekqiTo&q=85&s=8daa5889e4e5da861519a3380fffd8ec" alt="Router name configuration" width="3928" height="852" data-path="images/docs/cloud/networking/create-and-manage-a-router/create-router-name.png" />
    </Frame>

    ### Router control and route tables

    <p>Routing is based on route tables, which define the paths that network traffic takes from a VM to other destinations. These destinations can be inside or outside the private network. The tables contain static routes, which consist of a target subnet prefix in CIDR notation and the next hop's internal IP address (the virtual machine or router handling the traffic).</p>

    <p>Customers can add subnets to a router and define static routes for controlling traffic flow.</p>

    ## Manage routers

    <p>To manage routers:</p>

    1. Open the **Routers** page in the [Gcore Customer Portal](https://portal.gcore.com).

    2. Click the router name to access its settings. Alternatively, click the three-dot icon next to the router and select **Overview**.

    <Frame>
      <img src="https://mintcdn.com/gcore/gc7JxAc22A27n3nY/images/docs/cloud/networking/create-and-manage-a-router/router-name-highlighted.png?fit=max&auto=format&n=gc7JxAc22A27n3nY&q=85&s=f6db1e69e125e450a937a054fcf2b2cd" alt="Routers page with example router" width="1102" height="368" data-path="images/docs/cloud/networking/create-and-manage-a-router/router-name-highlighted.png" />
    </Frame>

    3. The **Router Details** page shows the router ID, SNAT status, creation date, and external IPs. Use the **SNAT** checkbox to allow instances in a private network to access external networks through the router. Subnets and static routes can also be configured from this page.

    <Frame>
      <img src="https://mintcdn.com/gcore/gc7JxAc22A27n3nY/images/docs/cloud/networking/create-and-manage-a-router/router-details-snat.png?fit=max&auto=format&n=gc7JxAc22A27n3nY&q=85&s=a27d28ed76f7e56ee4a683b07e1cfe8f" alt="Router Details page with SNAT toggle" width="1400" height="607" data-path="images/docs/cloud/networking/create-and-manage-a-router/router-details-snat.png" />
    </Frame>

    ### Configure a subnetwork

    <p>The **Subnets** section lists subnets attached to the router. New subnets can be added and existing ones deleted.</p>

    <p>When creating a subnetwork, pay attention to the supported CIDR ranges:</p>

    * 10.0.0.0/8
    * 172.16.0.0/12
    * 192.168.0.0/16
    * fc00::/7

    <Warning>
      A static route's next-hop IP must fall within the CIDR range of an attached subnet. If the subnet covering that next-hop is removed, traffic to the route destination will fail.
    </Warning>

    <p>Both IPv4 and IPv6 subnetworks are supported, but there are key differences. IPv4 is fully supported without restrictions. IPv6 has limitations: Floating IPs are not supported, private IPv6 subnets are not publicly routable, and only public IPv6 subnets can access the internet.</p>

    ## Configure static routes

    <p>There are two types of static routes: host routes (Layer 2) for internal subnet routing and router static routes (Layer 3) for inter-network traffic control.</p>

    ### Host routes for subnets (Layer 2)

    <p>Host routes operate at Layer 2 without relying on a router, controlling traffic flow within a subnet. They are delivered to instances through DHCP or cloud-init — DHCP dynamically assigns them based on subnet configuration, while cloud-init applies predefined settings at instance startup.</p>

    ### Router static routes (Layer 3)

    <p>Router-level static routes operate at Layer 3 and require a router to forward traffic between networks. When an instance sends traffic to a destination that matches a configured route, the router forwards it to the specified next-hop. When a router is present, it handles forwarding for all connected instances automatically.</p>

    <p>To configure a static route:</p>

    1. Go to the **Routers** page in the [Gcore Customer Portal](https://portal.gcore.com).

    2. Open the settings of the desired router.

    3. Open the **Static Routes** tab.

    4. Click **Edit Static Routes** → **Add Route**.

    <Frame>
      <img src="https://mintcdn.com/gcore/gc7JxAc22A27n3nY/images/docs/cloud/networking/create-and-manage-a-router/configure-static-routes.png?fit=max&auto=format&n=gc7JxAc22A27n3nY&q=85&s=8e4280cf21f60939084dcdeeef94501a" alt="Static routes settings" width="1286" height="534" data-path="images/docs/cloud/networking/create-and-manage-a-router/configure-static-routes.png" />
    </Frame>

    5. Enter Destination and Nexthop.

    6. Click **Save Static Routes**.

    <p>By default, subnets within the same network can communicate. This is because the default network router automatically unites all subnets within the network, enabling internal communication. However, traffic between different networks requires an explicit static route via a router.</p>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>Connect subnets to external networks and control traffic routing by creating a router and configuring static routes.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required, along with a [project ID](/api-reference/cloud/projects/list-projects) and [region ID](/api-reference/cloud/regions/list-regions).
    </Info>

    <p>Set these variables before running the examples:</p>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export GCORE_CLOUD_PROJECT_ID="{YOUR_PROJECT_ID}"
    export GCORE_CLOUD_REGION_ID="{YOUR_REGION_ID}"
    export SUBNET_ID="{YOUR_SUBNET_ID}"
    ```

    <Info>
      **SUBNET\_ID** is the UUID of the subnetwork to attach to the router. To create a subnetwork or find its ID, see [Create and manage a subnetwork](/cloud/networking/create-and-manage-a-subnetwork).
    </Info>

    ## Quickstart

    <p>The scripts below create a router with SNAT enabled, attach a subnet, add a static route, then verify the result.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import os
        from gcore import Gcore

        client = Gcore()

        # Step 1. Create a router with SNAT enabled.
        task = client.cloud.networks.routers.create(
            name="my-router",
            external_gateway_info={"type": "default", "enable_snat": True},
        )
        router_id = client.cloud.tasks.poll(task.tasks[0]).created_resources.routers[0]
        print(f"Router ID: {router_id}")

        # Step 2. Attach a subnet.
        router = client.cloud.networks.routers.attach_subnet(
            router_id,
            subnet_id=os.environ["SUBNET_ID"],
        )
        print(f"Attached subnet, interfaces: {len(router.interfaces)}")

        # Step 3. Add a static route.
        task = client.cloud.networks.routers.update(
            router_id,
            routes=[{"destination": "10.10.0.0/24", "nexthop": "192.168.100.1"}],
        )
        client.cloud.tasks.poll(task.tasks[0])

        # Step 4. Verify the result.
        router = client.cloud.networks.routers.get(router_id)
        print(f"Status: {router.status}  Routes: {len(router.routes)}  SNAT: {router.external_gateway_info.enable_snat}")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "log"
            "os"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            // Step 1. Create a router with SNAT enabled.
            router, err := client.Cloud.Networks.Routers.NewAndPoll(ctx, cloud.NetworkRouterNewParams{
                Name: "my-router",
                ExternalGatewayInfo: cloud.NetworkRouterNewParamsExternalGatewayInfoUnion{
                    OfRouterExternalDefaultGwSerializer: &cloud.NetworkRouterNewParamsExternalGatewayInfoRouterExternalDefaultGwSerializer{
                        Type:       "default",
                        EnableSnat: gcore.Bool(true),
                    },
                },
            })
            if err != nil {
                log.Fatalf("create router: %v", err)
            }
            fmt.Printf("Router ID: %s\n", router.ID)

            // Step 2. Attach a subnet.
            router, err = client.Cloud.Networks.Routers.AttachSubnet(ctx, router.ID, cloud.NetworkRouterAttachSubnetParams{
                SubnetID: os.Getenv("SUBNET_ID"),
            })
            if err != nil {
                log.Fatalf("attach subnet: %v", err)
            }
            fmt.Printf("Attached subnet, interfaces: %d\n", len(router.Interfaces))

            // Step 3. Add a static route.
            router, err = client.Cloud.Networks.Routers.UpdateAndPoll(ctx, router.ID, cloud.NetworkRouterUpdateParams{
                Routes: []cloud.NetworkRouterUpdateParamsRoute{
                    {Destination: "10.10.0.0/24", Nexthop: "192.168.100.1"},
                },
            })
            if err != nil {
                log.Fatalf("add route: %v", err)
            }
            fmt.Printf("Routes set: %d\n", len(router.Routes))

            // Step 4. Verify the result.
            router, err = client.Cloud.Networks.Routers.Get(ctx, router.ID, cloud.NetworkRouterGetParams{})
            if err != nil {
                log.Fatalf("get router: %v", err)
            }
            fmt.Printf("Status: %s\n", router.Status)
        }
        ```
      </Tab>
    </Tabs>

    ## Step-by-step

    <p>Each step below explains what the call does, which parameters matter, and what the response looks like. Use this section to understand the flow or to debug a specific step.</p>

    <Accordion title="Show all steps">
      ### Step 1. Create a router

      Provisions a new router; pass `external_gateway_info` with `type: "default"` to enable SNAT and give instances in private subnets access to the internet through this router.

      | Parameter                           | Required | Description                                                                                                              |
      | ----------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
      | `name`                              | Yes      | Name for the router.                                                                                                     |
      | `external_gateway_info.type`        | No       | Set to `"default"` to auto-select the external network for this region. Omit to create a router without internet access. |
      | `external_gateway_info.enable_snat` | No       | Set to `true` to enable SNAT. Required when `type` is `"default"`.                                                       |
      | `interfaces`                        | No       | List of subnets to attach at creation, each as `{"subnet_id": "..."}`.                                                   |
      | `routes`                            | No       | List of static routes at creation, each as `{"destination": "CIDR", "nexthop": "IP"}`.                                   |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          task = client.cloud.networks.routers.create(
              name="my-router",
              external_gateway_info={"type": "default", "enable_snat": True},
          )
          router_id = client.cloud.tasks.poll(task.tasks[0]).created_resources.routers[0]
          print(f"Router ID: {router_id}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          router, err := client.Cloud.Networks.Routers.NewAndPoll(ctx, cloud.NetworkRouterNewParams{
              Name: "my-router",
              ExternalGatewayInfo: cloud.NetworkRouterNewParamsExternalGatewayInfoUnion{
                  OfRouterExternalDefaultGwSerializer: &cloud.NetworkRouterNewParamsExternalGatewayInfoRouterExternalDefaultGwSerializer{
                      Type:       "default",
                      EnableSnat: gcore.Bool(true),
                  },
              },
          })
          if err != nil {
              log.Fatalf("create router: %v", err)
          }
          fmt.Printf("Router ID: %s\n", router.ID)
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X POST "https://api.gcore.com/cloud/v1/routers/${PROJECT_ID}/${REGION_ID}" \
            -H "Authorization: APIKey ${GCORE_API_KEY}" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "my-router",
              "external_gateway_info": { "type": "default", "enable_snat": true }
            }'
          ```

          Response:

          ```json theme={null}
          {
            "tasks": ["d8de6c30-6502-45a1-94b0-790709e40e78"]
          }
          ```

          Poll `GET /cloud/v1/tasks/{task_id}` every 5 seconds until `state` is `FINISHED`. The router ID is in `created_resources.routers[0]`.

          ```json theme={null}
          {
            "state": "FINISHED",
            "created_resources": {
              "routers": ["da5b9588-cecc-4111-a318-3ad04da05900"]
            }
          }
          ```
        </Tab>
      </Tabs>

      ### Step 2. Attach a subnet

      Connects a subnet to the router so instances in that subnet can use the router for traffic forwarding. The router assigns an interface IP from within the subnet range automatically.

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          router = client.cloud.networks.routers.attach_subnet(
              router_id,
              subnet_id=os.environ["SUBNET_ID"],
          )
          print(f"Interfaces: {len(router.interfaces)}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          router, err = client.Cloud.Networks.Routers.AttachSubnet(ctx, router.ID, cloud.NetworkRouterAttachSubnetParams{
              SubnetID: os.Getenv("SUBNET_ID"),
          })
          if err != nil {
              log.Fatalf("attach subnet: %v", err)
          }
          fmt.Printf("Interfaces: %d\n", len(router.Interfaces))
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X POST "https://api.gcore.com/cloud/v1/routers/${PROJECT_ID}/${REGION_ID}/${ROUTER_ID}/attach" \
            -H "Authorization: APIKey ${GCORE_API_KEY}" \
            -H "Content-Type: application/json" \
            -d '{ "subnet_id": "'${SUBNET_ID}'" }'
          ```

          Response:

          ```json theme={null}
          {
            "id": "da5b9588-cecc-4111-a318-3ad04da05900",
            "name": "my-router",
            "status": "ACTIVE",
            "interfaces": [
              {
                "port_id": "43421eaf-b298-4bab-b9c4-c8cf296246f7",
                "ip_assignments": [
                  { "subnet_id": "a87cedcc-ac14-4133-a26e-8da113a522b2", "ip_address": "192.168.100.236" }
                ],
                "network_id": "6880a081-5f09-4437-9942-3eabee038666"
              }
            ],
            "routes": [],
            "external_gateway_info": { "enable_snat": true }
          }
          ```
        </Tab>
      </Tabs>

      ### Step 3. Get router details

      Returns the full router object including attached interfaces, configured routes, SNAT status, and external gateway information.

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          router = client.cloud.networks.routers.get(router_id)
          print(f"Status: {router.status}  SNAT: {router.external_gateway_info.enable_snat}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          router, err = client.Cloud.Networks.Routers.Get(ctx, router.ID, cloud.NetworkRouterGetParams{})
          if err != nil {
              log.Fatalf("get router: %v", err)
          }
          fmt.Printf("Status: %s\n", router.Status)
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X GET "https://api.gcore.com/cloud/v1/routers/${PROJECT_ID}/${REGION_ID}/${ROUTER_ID}" \
            -H "Authorization: APIKey ${GCORE_API_KEY}"
          ```

          Response:

          ```json theme={null}
          {
            "id": "da5b9588-cecc-4111-a318-3ad04da05900",
            "name": "my-router",
            "status": "ACTIVE",
            "external_gateway_info": {
              "network_id": "4e16750d-2656-4038-9411-3c7f06c62643",
              "enable_snat": true,
              "external_fixed_ips": [
                { "subnet_id": "78bf97c9-32c4-4dff-9fcf-2bdcf7e7a542", "ip_address": "109.61.46.198" }
              ]
            },
            "interfaces": [
              {
                "ip_assignments": [
                  { "subnet_id": "a87cedcc-ac14-4133-a26e-8da113a522b2", "ip_address": "192.168.100.236" }
                ],
                "network_id": "6880a081-5f09-4437-9942-3eabee038666"
              }
            ],
            "routes": []
          }
          ```
        </Tab>
      </Tabs>

      ### Step 4. Add static routes

      <p>Static routes direct traffic to a destination CIDR via a specified next-hop IP. The `PATCH` call replaces the full routes list — include all routes on every update.</p>

      | Parameter     | Description                                                  |
      | ------------- | ------------------------------------------------------------ |
      | `destination` | Target network in CIDR notation, e.g. `10.10.0.0/24`.        |
      | `nexthop`     | IP address of the next-hop device within an attached subnet. |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          task = client.cloud.networks.routers.update(
              router_id,
              routes=[{"destination": "10.10.0.0/24", "nexthop": "192.168.100.1"}],
          )
          client.cloud.tasks.poll(task.tasks[0])
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          router, err = client.Cloud.Networks.Routers.UpdateAndPoll(ctx, router.ID, cloud.NetworkRouterUpdateParams{
              Routes: []cloud.NetworkRouterUpdateParamsRoute{
                  {Destination: "10.10.0.0/24", Nexthop: "192.168.100.1"},
              },
          })
          if err != nil {
              log.Fatalf("update routes: %v", err)
          }
          fmt.Printf("Routes set: %d\n", len(router.Routes))
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X PATCH "https://api.gcore.com/cloud/v1/routers/${PROJECT_ID}/${REGION_ID}/${ROUTER_ID}" \
            -H "Authorization: APIKey ${GCORE_API_KEY}" \
            -H "Content-Type: application/json" \
            -d '{
              "routes": [
                { "destination": "10.10.0.0/24", "nexthop": "192.168.100.1" }
              ]
            }'
          ```

          Response:

          ```json theme={null}
          {
            "tasks": ["7282ccc2-7da8-452e-86d2-5254fed23321"]
          }
          ```

          Poll `GET /cloud/v1/tasks/{task_id}` until `state` is `FINISHED`, then call `GET /cloud/v1/routers/{id}` to confirm the routes are applied.
        </Tab>
      </Tabs>

      <Warning>A subnet cannot be detached while a static route uses a next-hop IP within that subnet's range. Clear the routes list first by sending an empty `routes` array before detaching the subnet.</Warning>
    </Accordion>

    ## Clean up

    <p>Detach the subnet before deleting the router. If static routes reference the subnet's IP range, clear them first by sending an empty `routes` array via `PATCH`.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        # Clear routes first (required if a nexthop IP belongs to the subnet).
        task = client.cloud.networks.routers.update(router_id, routes=[])
        client.cloud.tasks.poll(task.tasks[0])

        # Detach the subnet.
        client.cloud.networks.routers.detach_subnet(router_id, subnet_id=os.environ["SUBNET_ID"])

        # Delete the router.
        task = client.cloud.networks.routers.delete(router_id)
        client.cloud.tasks.poll(task.tasks[0])
        print(f"Deleted router {router_id}")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        // Clear routes first (required if a nexthop IP belongs to the subnet).
        if _, err = client.Cloud.Networks.Routers.UpdateAndPoll(ctx, router.ID, cloud.NetworkRouterUpdateParams{
            Routes: []cloud.NetworkRouterUpdateParamsRoute{},
        }); err != nil {
            log.Fatalf("clear routes: %v", err)
        }

        // Detach the subnet.
        if _, err = client.Cloud.Networks.Routers.DetachSubnet(ctx, router.ID, cloud.NetworkRouterDetachSubnetParams{
            SubnetID: cloud.SubnetIDParam{SubnetID: os.Getenv("SUBNET_ID")},
        }); err != nil {
            log.Fatalf("detach subnet: %v", err)
        }

        // Delete the router.
        if err = client.Cloud.Networks.Routers.DeleteAndPoll(ctx, router.ID, cloud.NetworkRouterDeleteParams{}); err != nil {
            log.Fatalf("delete router: %v", err)
        }
        fmt.Println("Router deleted.")
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        # Detach the subnet.
        curl -X POST "https://api.gcore.com/cloud/v1/routers/${PROJECT_ID}/${REGION_ID}/${ROUTER_ID}/detach" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{ "subnet_id": "'${SUBNET_ID}'" }'

        # Delete the router.
        curl -X DELETE "https://api.gcore.com/cloud/v1/routers/${PROJECT_ID}/${REGION_ID}/${ROUTER_ID}" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Response:

        ```json theme={null}
        {
          "tasks": ["b972d19f-1dba-4478-ba97-9a4483ee865a"]
        }
        ```
      </Tab>
    </Tabs>
  </MethodSection>

  <MethodSection id="terraform" label="Terraform">
    <p>Add a cloud router to enable outbound internet access via SNAT and routing between subnets. The [`gcore_cloud_network_router`](https://registry.terraform.io/providers/G-Core/gcore/latest/docs/resources/cloud_network_router) resource handles gateway configuration and static route management.</p>

    <Info>
      `var.subnet_id` references a subnet from [Create and manage a subnetwork](/cloud/networking/create-and-manage-a-subnetwork).
    </Info>

    ## Create a router

    <p>Declares a router with SNAT enabled and a subnet interface. Set `type = "default"` to let the provider select the region's external network automatically.</p>

    ```hcl theme={null}
    resource "gcore_cloud_network_router" "example" {
      project_id = var.project_id
      region_id  = var.region_id
      name       = "my-router"

      external_gateway_info = {
        type        = "default"
        enable_snat = true
      }

      interfaces = [{
        subnet_id = var.subnet_id
        type      = "subnet"
      }]
    }

    output "router_id" {
      value = gcore_cloud_network_router.example.id
    }
    ```

    <Warning>
      After the first `terraform apply`, the provider resolves `type = "default"` into a concrete external network ID. To make any subsequent change to the router, update `external_gateway_info`: set `type = "manual"` and copy `external_gateway_info.network_id` from `terraform show`.
    </Warning>

    ## Add static routes

    <p>Edit the `routes` block and run `terraform apply`. The provider replaces the entire routes list on each update — include all active routes in the block.</p>

    ```hcl theme={null}
    resource "gcore_cloud_network_router" "example" {
      project_id = var.project_id
      region_id  = var.region_id
      name       = "my-router"

      external_gateway_info = {
        type        = "manual"
        network_id  = "<external-network-id>"  # from terraform show
        enable_snat = true
      }

      interfaces = [{
        subnet_id = var.subnet_id
        type      = "subnet"
      }]

      routes = [{
        destination = "10.10.0.0/24"
        nexthop     = "192.168.30.1"
      }]
    }
    ```

    ```bash theme={null}
    terraform apply
    ```

    ## Delete a router

    <p>Remove the resource block — Terraform detects the missing declaration and deletes the router on the next `terraform apply`.</p>

    ```hcl theme={null}
    # Remove or comment out this block:
    # resource "gcore_cloud_network_router" "example" {
    #   name       = "my-router"
    #   project_id = var.project_id
    #   region_id  = var.region_id
    #   ...
    # }
    ```

    ```bash theme={null}
    terraform apply
    ```

    ## Import a router

    <p>Use when a router was created outside Terraform and needs to be managed as code.</p>

    ```hcl theme={null}
    resource "gcore_cloud_network_router" "example" {
      project_id = var.project_id
      region_id  = var.region_id
      name       = "my-router"

      external_gateway_info = {
        type        = "manual"
        network_id  = "<external-network-id>"
        enable_snat = true
      }

      interfaces = [{
        subnet_id = var.subnet_id
        type      = "subnet"
      }]
    }
    ```

    ```bash theme={null}
    terraform import gcore_cloud_network_router.example '<project_id>/<region_id>/<router_id>'
    ```
  </MethodSection>
</MethodSwitch>
