curl --request POST \
--url https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"interface": "e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d"
}
'import requests
url = "https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics"
payload = { "interface": "e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({interface: 'e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d'})
};
fetch('https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'interface' => 'e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics"
payload := strings.NewReader("{\n \"interface\": \"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"interface\": \"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"interface\": \"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d\"\n}"
response = http.request(request)
puts response.read_body{
"attachment": {
"interface_id": "e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d",
"mac": "02:1a:2b:3c:4d:5e",
"boot_index": 0,
"external": false,
"restart_required": true,
"addresses": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"family": "ipv4",
"address": "<string>",
"prefix": "<string>",
"primary": true,
"floating_ips": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"crn": "<string>",
"visibility": "public",
"address": "<string>"
}
]
}
]
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "ACCESS_DENIED",
"message": "You don't have permission to perform this action",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "This Idempotency-Key was already used with a different request payload",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}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.
curl --request POST \
--url https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"interface": "e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d"
}
'import requests
url = "https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics"
payload = { "interface": "e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({interface: 'e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d'})
};
fetch('https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'interface' => 'e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics"
payload := strings.NewReader("{\n \"interface\": \"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"interface\": \"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.{region}.basaltic.sh/v1/instances/{instance_id}/nics")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"interface\": \"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d\"\n}"
response = http.request(request)
puts response.read_body{
"attachment": {
"interface_id": "e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d",
"mac": "02:1a:2b:3c:4d:5e",
"boot_index": 0,
"external": false,
"restart_required": true,
"addresses": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"family": "ipv4",
"address": "<string>",
"prefix": "<string>",
"primary": true,
"floating_ips": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"crn": "<string>",
"visibility": "public",
"address": "<string>"
}
]
}
]
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "ACCESS_DENIED",
"message": "You don't have permission to perform this action",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "This Idempotency-Key was already used with a different request payload",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}compute:AttachNIC. See COMPUTE permissions for the full list, what each one covers, and an example policy.Authorizations
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.
Headers
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.
255Path Parameters
Instance ID
Body
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.
1"e8a1c2d3-4b5f-4a6e-9c0d-1e2f3a4b5c6d"
Response
Attachment accepted
Show child attributes
Show child attributes