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

# Attach an existing NIC to an instance

> Attaches an existing standalone network interface. The instance
must be running or stopped. To create an interface, use
`POST /v1/interfaces` on the Network API before attaching it.
This operation never provisions an interface.

The attachment is durable the moment this returns: it is part
of the instance's spec and survives reboots. Delivery to the
guest is asynchronous and the response says what it takes.

A stopped instance comes up with the device, and
`restart_required` is absent. A running instance is given the
device while it runs where the region supports that: the call
returns before the guest has it, `restart_required` is absent,
and the interface appears in the guest moments later — poll
`GET /v1/instances/{instance_id}/nics`, or watch the guest for
a link carrying the MAC in this response. Where the region does
not, the response sets `restart_required`: reboot the instance
with `{"hard": true}` to deliver it. A soft reboot is ACPI
inside the same launcher and will not.

The address is DHCP's either way. Nothing configures the new
interface inside the guest, so an image that does not bring up
a network device when it appears (cloud-init hotplug,
NetworkManager, systemd-networkd with a wildcard match) holds
the link without an address until something in the guest asks
for the lease.


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


## OpenAPI

````yaml /api-reference/specs/compute.yaml post /v1/instances/{instance_id}/nics
openapi: 3.0.3
info:
  title: Basaltic Compute API
  version: 1.0.0
  description: |
    Virtual machine instances, and the images, flavors, SSH keypairs and
    instance pools they are built from. Covers the whole instance lifecycle:
    start, stop, reboot, resize and reinstall.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://compute.{region}.basaltic.sh
    description: Regional API endpoint
    variables:
      region:
        default: sa-saopaulo-1
        description: Region code
security:
  - BearerAuth: []
paths:
  /v1/instances/{instance_id}/nics:
    post:
      tags:
        - Compute
      summary: Attach an existing NIC to an instance
      description: |
        Attaches an existing standalone network interface. The instance
        must be running or stopped. To create an interface, use
        `POST /v1/interfaces` on the Network API before attaching it.
        This operation never provisions an interface.

        The attachment is durable the moment this returns: it is part
        of the instance's spec and survives reboots. Delivery to the
        guest is asynchronous and the response says what it takes.

        A stopped instance comes up with the device, and
        `restart_required` is absent. A running instance is given the
        device while it runs where the region supports that: the call
        returns before the guest has it, `restart_required` is absent,
        and the interface appears in the guest moments later — poll
        `GET /v1/instances/{instance_id}/nics`, or watch the guest for
        a link carrying the MAC in this response. Where the region does
        not, the response sets `restart_required`: reboot the instance
        with `{"hard": true}` to deliver it. A soft reboot is ACPI
        inside the same launcher and will not.

        The address is DHCP's either way. Nothing configures the new
        interface inside the guest, so an image that does not bring up
        a network device when it appears (cloud-init hotplug,
        NetworkManager, systemd-networkd with a wildcard match) holds
        the link without an address until something in the guest asks
        for the lease.
      operationId: attachInstanceNIC
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/InstanceId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - interface
              properties:
                interface:
                  type: string
                  minLength: 1
                  description: >-
                    Existing standalone interface UUID or complete
                    VPC/subnet/interface CRN. Bare names lack the subnet parent
                    and are rejected. It keeps its address, MAC, and security
                    groups; detach returns it to standalone instead of
                    destroying it.
                  example: e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d
      responses:
        '202':
          description: Attachment accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  attachment:
                    type: object
                    properties:
                      interface_id:
                        type: string
                        example: e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d
                      mac:
                        type: string
                        example: 02:1a:2b:3c:4d:5e
                      boot_index:
                        type: integer
                        example: 0
                      external:
                        type: boolean
                        description: >-
                          The attached interface existed before this call
                          (interface was given). Detach unbinds it and leaves it
                          standalone rather than destroying it.
                        example: false
                      restart_required:
                        type: boolean
                        description: >-
                          The guest does not carry the interface yet and a hard
                          reboot is what delivers it — an interface past the
                          first is a network on the instance's launcher, and a
                          launcher's networks are fixed for its lifetime. Set
                          when the instance was running in a region that cannot
                          attach to a running guest. Absent for a stopped
                          instance, which comes up with the device, and absent
                          where the region attaches live, where the running
                          guest is given the device without a restart.
                        example: true
                      addresses:
                        type: array
                        items:
                          $ref: '#/components/schemas/InterfaceAddress'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Instance not in a state that allows NIC attach
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
      security:
        - BearerAuth: []
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      description: >-
        Optional client-generated key that makes a create replay-safe. Retrying
        a request with the same key returns the original outcome verbatim
        instead of creating a duplicate resource. Reusing a key with a different
        request body is rejected (422); a request whose key is still being
        processed returns 409. Records are honored for 24 hours. Use a UUID or
        similarly unique token.
      required: false
      schema:
        type: string
        maxLength: 255
      example: 550e8400-e29b-41d4-a716-446655440000
    InstanceId:
      name: instance_id
      in: path
      description: Instance ID
      required: true
      schema:
        type: string
        format: uuid
      example: 550e8400-e29b-41d4-a716-446655440000
  schemas:
    InterfaceAddress:
      type: object
      properties:
        id:
          type: string
          format: uuid
        family:
          type: string
          enum:
            - ipv4
            - ipv6
        address:
          type: string
        prefix:
          type: string
          description: >-
            Owned allocation, not the guest netmask: IPv4 /32 or IPv6 /96.
            DHCPv6 configures the first /128.
        primary:
          type: boolean
        floating_ips:
          type: array
          items:
            $ref: '#/components/schemas/AddressFloatingIp'
      required:
        - id
        - family
        - address
        - prefix
        - primary
        - floating_ips
    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
            request_id:
              type: string
              format: uuid
              description: Request ID for debugging
              example: 550e8400-e29b-41d4-a716-446655440000
    AddressFloatingIp:
      type: object
      properties:
        id:
          type: string
          format: uuid
        crn:
          type: string
        visibility:
          type: string
          enum:
            - public
            - private
        address:
          type: string
      required:
        - id
        - crn
        - visibility
        - address
  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
    UnprocessableEntity:
      description: |
        The request is well-formed but cannot be processed as sent. On the
        operations that accept `Idempotency-Key` this is the key-reuse case: the
        key was first seen with a different request payload, so replaying the
        stored outcome would answer a question the caller did not ask.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: IDEMPOTENCY_KEY_REUSED
              message: >-
                This Idempotency-Key was already used with a different request
                payload
              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.

````