> ## Documentation Index
> Fetch the complete documentation index at: https://gcore.com/docs/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 enables you to dynamically exchange routes between networks. You can find the list of routers in networking settings, on the **Routers** page.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore/c-GSw73gRYekqiTo/images/docs/cloud/networking/create-and-manage-a-router/routers-page.png?fit=max&auto=format&n=c-GSw73gRYekqiTo&q=85&s=88f416a43ea08dcc3c72beb170eff0d1" alt="Routers page in the Customer Portal" width="1782" height="825" data-path="images/docs/cloud/networking/create-and-manage-a-router/routers-page.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.

    * After you create a [network](/cloud/networking/create-and-manage-a-network), a new router is automatically created in the cloud to enable traffic routing. You can configure automatically created routers using the same settings available for manually created routers.

    ### Create a router manually

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

    <p>2. Go to the **Routers** page and click **Create router**.</p>

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

    <p>3. Select the network and subnetwork to configure routing. If necessary, you can add multiple subnetworks by clicking on **Add Subnet**. For more information about creating and configuring a network and subnetwork, refer to our [Networking](/cloud/networking/create-and-manage-a-network) guide.</p>

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

    <p>4. (Optional) Turn on the **Enable SNAT** toggle if you need access to the external network. A separate public IP address is announced for a router with access to an external network. This setting can be changed at any time after the router is created.</p>

    <p>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.</p>

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

    <p>6. Give your router a name and save the configuration by clicking **Create Router**.</p>

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

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

    <p>2. Click the router name to access its settings. Alternatively, click the three-dot icon next to the router you want to manage and then select **Overview**.</p>

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

    <p>3. On the router overview page, you can find general information such as router ID, SNAT status, creation dates, and external IPs. Use the SNAT toggle to allow instances in a private network to access external networks through the router. You can also configure and add new subnetworks and update static routes.</p>

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

    ### Configure a subnetwork

    <p>In the **Subnets** section, you can manage the list of subnets added to the router, add new subnets, and delete the existing ones.</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>
      **Warning**

      The specified CIDR ranges must align with the destinations configured in your static routes.
    </Warning>

    <p>We support both IPv4 and IPv6 subnetworks, 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 assigned to instances through DHCP or cloud-init instead of being distributed by a router. DHCP dynamically assigns host routes based on network configurations, while cloud-init configures them automatically at instance startup using predefined settings.</p>

    <p>Host routes are automatically assigned to instances within the same subnet and do not require manual configuration. They are not advertised beyond the subnet, ensuring traffic stays internal.</p>

    ### Router static routes (Layer 3)

    <p>Router-level static routes operate at Layer 3 and require a router to forward traffic between networks. These routes are distributed to instances using Router Advertisement. When a router is present, it announces available routes to connected instances.</p>

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

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

    <p>2. Open the settings of the desired router.</p>

    <p>3. Open the **Static Routes** tab.</p>

    <p>4. Click **Edit Static Routes** → **Add Route**.</p>

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

    <p>5. Enter Destination and Nexthop.</p>

    <p>6. Click **Save Static Routes**.</p>

    <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, verify the result, then delete the router.</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>
    </Accordion>

    ## Add static routes

    <p>Static routes direct traffic from the router to a destination CIDR through 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>

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