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

# Enable IPv6 on a subnet

> Assign an IPv6 range after creation. Existing ranges cannot be replaced.

<Info>
  Requires the IAM action **`network:UpdateSubnet`**. See [NETWORK permissions](/networking/permissions) for the full list, what each one covers, and an example policy.
</Info>


## OpenAPI

````yaml /api-reference/specs/network.yaml post /v1/subnets/{subnet_id}/ipv6
openapi: 3.0.3
info:
  title: Basaltic Network API
  version: 1.0.0
  description: |
    The VPC surface — networks and subnets, interfaces, route tables,
    security groups, internet, NAT and egress-only gateways, and floating
    IPs.

    Relationship inputs use one reference field: UUID, CRN, or an exact name
    when the request supplies its required parent scope. Subnets and route
    tables are VPC-scoped; interfaces are subnet-scoped. Nested CRNs use
    vpc/<vpc>/subnet/<subnet>, vpc/<vpc>/route-table/<table>, and
    vpc/<vpc>/subnet/<subnet>/interface/<interface>. Names are immutable.
    Unknown request fields and list parameters are rejected.
    Supplied empty references are invalid and failed lookups never fall back
    to another reference kind. Every list accepts exact name and crn filters.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://network.{region}.basaltic.sh
    description: Regional API endpoint
    variables:
      region:
        default: sa-saopaulo-1
        description: Region code
security:
  - BearerAuth: []
paths:
  /v1/subnets/{subnet_id}/ipv6:
    post:
      tags:
        - Networking
      summary: Enable IPv6 on a subnet
      description: Assign an IPv6 range after creation. Existing ranges cannot be replaced.
      operationId: enableSubnetIPv6
      parameters:
        - $ref: '#/components/parameters/SubnetId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubnetIPv6Request'
      responses:
        '200':
          description: IPv6 enabled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubnetResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
components:
  parameters:
    SubnetId:
      name: subnet_id
      in: path
      description: Subnet ID
      required: true
      schema:
        type: string
        format: uuid
      example: 550e8400-e29b-41d4-a716-446655440000
  schemas:
    SubnetIPv6Request:
      type: object
      additionalProperties: false
      description: >-
        Provide allocate_cidr_ipv6 as true or a nonempty cidr_ipv6. Existing
        IPv6 ranges cannot be replaced.
      anyOf:
        - required:
            - allocate_cidr_ipv6
        - required:
            - cidr_ipv6
      properties:
        allocate_cidr_ipv6:
          type: boolean
          default: false
          description: >-
            Allocate a free /64 from the VPC IPv6 range. Can be enabled after
            creation. Every existing and new interface receives an IPv6 /96 and
            its first /128 automatically. NAT gateways hosted here also receive
            a public IPv6 address from the regional pool. Updating hosted
            gateways requires UpdateNATGateway permission and public IPv6 quota.
        cidr_ipv6:
          type: string
          description: >-
            An aligned /64 inside the VPC IPv6 range. Can be added later; cannot
            replace an existing range. Mutually exclusive with
            allocate_cidr_ipv6.
          example: 2a13:9500:1a6:100::/64
        copy_ipv4_security_rules:
          type: boolean
          default: true
          description: >-
            When enabling IPv6, copy equivalent rules in security groups used by
            this subnet's interfaces. Copies 0.0.0.0/0 to ::/0 and
            security-group references, preserving protocol, ports and direction.
            Restricted IPv4 CIDRs are not widened. Existing IPv6 equivalents are
            not duplicated. Changes affect every interface sharing these groups.
            Requires CreateSecurityGroupRule permission and available rule
            quota. Only accepted with allocate_cidr_ipv6 or cidr_ipv6.
        ipv6_routing:
          type: string
          enum:
            - match_ipv4
            - unchanged
            - internet_gateway
            - nat_gateway
            - egress_only_gateway
          default: match_ipv4
          description: >-
            When enabling IPv6, optionally add ::/0 to the subnet's route table.
            match_ipv4 follows an IPv4 internet-gateway or NAT-gateway default
            route, using the same target. A NAT gateway must already have IPv6
            enabled on its hosting subnet, or be hosted in the subnet being
            enabled. No IPv4 default route leaves IPv6 routing unchanged.
            Existing IPv6 default routes are always preserved. Egress-only
            gateways cannot provide ULA internet access; use a NAT gateway, or a
            public IPv6 floating IP with an internet-gateway route. Changes
            affect every subnet sharing the route table and require CreateRoute
            permission; creating an egress-only gateway also requires
            CreateEgressOnlyGateway permission. Only accepted with
            allocate_cidr_ipv6 or cidr_ipv6.
    SubnetResponse:
      type: object
      required:
        - subnet
      properties:
        subnet:
          $ref: '#/components/schemas/Subnet'
    Subnet:
      type: object
      required:
        - id
        - crn
        - vpc
        - route_table
        - name
        - cidr_ipv4
        - gateway_ipv4
        - tags
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        crn:
          type: string
          readOnly: true
          example: crn:network:sa-saopaulo-1:my-account:vpc/prod/subnet/prod-web
        vpc:
          $ref: '#/components/schemas/ResourceRef'
        route_table:
          anyOf:
            - $ref: '#/components/schemas/ResourceRef'
            - type: object
              nullable: true
              enum:
                - null
          description: >-
            Route table associated with this subnet; null when the table is
            unavailable.
        name:
          description: >-
            Resource names must not start with the literal crn: prefix or be
            UUIDs (canonical, compact, braced, or urn:uuid: forms, in either
            case).
          type: string
          example: prod-web
        description:
          type: string
          example: Public web-tier subnet
        cidr_ipv4:
          type: string
          example: 10.0.1.0/24
        gateway_ipv4:
          type: string
          example: 10.0.1.1
        cidr_ipv6:
          type: string
          nullable: true
          readOnly: true
          description: >-
            The dual-stack IPv6 /64, if the subnet is v6-enabled. Its presence
            (vs the v4 cidr_ipv4) is how a client tells the subnet's families
            apart.
          example: 2a13:9500:1a6:100::/64
        gateway_ipv6:
          type: string
          nullable: true
          readOnly: true
          example: 2a13:9500:1a6:100::1
        tags:
          type: object
          additionalProperties:
            type: string
        created_at:
          type: string
          format: date-time
          readOnly: true
        updated_at:
          type: string
          format: date-time
          readOnly: true
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: Error code identifying the type of error
              example: INVALID_INPUT
            message:
              type: string
              description: Human-readable error message
              example: Invalid request parameters
            params:
              type: object
              additionalProperties: true
              description: >-
                Optional non-sensitive values for interpolation of localized
                errors, keyed by error code. Never present for server errors.
              example:
                instances: 2
                pools: 0
            request_id:
              type: string
              format: uuid
              description: Request ID for debugging
              example: 550e8400-e29b-41d4-a716-446655440000
    ResourceRef:
      type: object
      required:
        - id
        - crn
      properties:
        id:
          type: string
          format: uuid
          example: 288aa1e9-bbf5-5584-bce9-6a688f06d8a1
        crn:
          type: string
          example: crn:catalog::platform:country/288aa1e9-bbf5-5584-bce9-6a688f06d8a1
        name:
          type: string
          description: >-
            Display label at response time — the resource's name where it has
            one, otherwise its human label (an invoice number, an account
            display name). Absent when the target is gone. Not a lookup key.
          example: Brazil
  responses:
    BadRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INVALID_INPUT
              message: Invalid request parameters
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Unauthorized:
      description: Authentication required or token invalid
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: UNAUTHORIZED
              message: Authentication required
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Forbidden:
      description: Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ACCESS_DENIED
              message: You don't have permission to perform this action
              request_id: 550e8400-e29b-41d4-a716-446655440000
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: NOT_FOUND
              message: Resource not found
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Conflict:
      description: Resource conflict (e.g., already exists, invalid state)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: CONFLICT
              message: Resource with this name already exists
              request_id: 550e8400-e29b-41d4-a716-446655440000
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INTERNAL_ERROR
              message: An internal error occurred
              request_id: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        An OAuth 2.0 bearer token, sent as `Authorization: Bearer <token>`.
        This is the recommended way to authenticate.

        Get one by exchanging a service account's access key pair at
        `POST /v1/oauth/token` with `grant_type=client_credentials`. It is the
        standard client-credentials grant, so any OAuth-aware library will
        obtain and refresh it for you.

        ```
        curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
          https://iam.basaltic.sh/v1/oauth/token
        ```

        Tokens last an hour by default. The same access key pair is separately
        your AWS SigV4 credential for the S3-compatible object endpoint, which
        speaks nothing else.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.