# Integrating with Orchard Orchard has a REST API that follows [OpenAPI specification](https://swagger.io/specification/) and is described in `api/openapi.yaml`. You can run `orchard dev` locally and navigate to http://127.0.0.1:6120/v1/ for interactive documentation. ![](docs/orchard-api-documentation-browser.png) ## Using the API Below you'll find examples of using Orchard API via vanilla Python's request library and Golang package that Orchard CLI build on top of. ### Authentication When running in non-development mode, Orchard API expects a [basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) to be provided for each API call. Below you'll find two snippets that retrieve controller's information and output its version: **Python** ```python import requests from requests.auth import HTTPBasicAuth def main(): # Authentication basic_auth = HTTPBasicAuth("service account name", "service account token") response = requests.get("http://127.0.0.1:6120/v1/info", auth=basic_auth) print(response.json()["version"]) if __name__ == '__main__': main() ``` **Golang** ```go package main import ( "context" "fmt" "github.com/cirruslabs/orchard/pkg/client" "log" ) func main() { client, err := client.New() if err != nil { log.Fatalf("failed to initialize Orchard API client: %v", err) } controllerInfo, err := client.Controller().Info(context.Background()) if err != nil { log.Fatalf("failed to retrieve controller's information: %v", err) } fmt.Println(controllerInfo.Version) } ``` Note that we don't provide any credentials for Golang's version of the snippet: this is because Orchard's Golang API client (`github.com/cirruslabs/orchard/pkg/client`) has the ability to read the current's user Orchard context automatically. ### Creating a VM A more intricate example would be spinning off a VM with a startup script that outputs date, reading its logs and removing it from the controller: **Python** ```python import time import uuid import requests from requests.auth import HTTPBasicAuth def main(): vm_name = str(uuid.uuid4()) basic_auth = HTTPBasicAuth("service account name", "service account token") # Create VM response = requests.post("http://127.0.0.1:6120/v1/vms", auth=basic_auth, json={ "name": vm_name, "image": "ghcr.io/cirruslabs/macos-sonoma-base:latest", "cpu": 4, "memory": 4096, "startup_script": { "script_content": "date", } }) response.raise_for_status() # Retrieve VM's logs while True: response = requests.get(f"http://127.0.0.1:6120/v1/vms/{vm_name}/events", auth=basic_auth) response.raise_for_status() result = response.json() if isinstance(result, list) and len(result) != 0: print(result[0]["payload"]) break time.sleep(1) # Delete VM response = requests.delete(f"http://127.0.0.1:6120/v1/vms/{vm_name}", auth=basic_auth) response.raise_for_status() if __name__ == '__main__': main() ``` **Golang** ```go package main import ( "context" "fmt" "github.com/cirruslabs/orchard/pkg/client" v1 "github.com/cirruslabs/orchard/pkg/resource/v1" "github.com/google/uuid" "log" "time" ) func main() { vmName := uuid.New().String() client, err := client.New() if err != nil { log.Fatalf("failed to initialize Orchard API client: %v", err) } // Create VM err = client.VMs().Create(context.Background(), &v1.VM{ Meta: v1.Meta{ Name: vmName, }, Image: "ghcr.io/cirruslabs/macos-sonoma-base:latest", CPU: 4, Memory: 4096, StartupScript: &v1.VMScript{ ScriptContent: "date", }, }) if err != nil { log.Fatalf("failed to create VM: %v") } // Retrieve VM's logs for { vmLogs, err := client.VMs().Logs(context.Background(), vmName) if err != nil { log.Fatalf("failed to retrieve VM logs") } if len(vmLogs) != 0 { fmt.Println(vmLogs[0]) break } time.Sleep(time.Second) } // Delete VM if err := client.VMs().Delete(context.Background(), vmName); err != nil { log.Fatalf("failed to delete VM: %v", err) } } ``` ## Resource management Some resources, such as `Worker` and `VM`, have a `resource` field which is a dictionary that maps between resource names and their amounts (amount requested or amount provided, depending on the resource) and is useful for scheduling. Well-known resources: * `org.cirruslabs.tart-vms` — number of Tart VM slots available on the machine or requested by the VM * this number is `2` for workers and `1` for VMs by default