Cowboy in the desert.

Importing variables with the Octopus REST API

Octopus 2.0 introduced a comprehensive REST API that can be used to perform anything that the UI can perform. We know this because the UI itself is built completely on top of the REST API. Today a couple of people asked how they can automatically import variables using the API, which I'll demonstrate below.

Collections of variables are stored in a VariableSet resource. When editing variables in the UI, you are editing the VariableSet. For example, in this screenshot, the four variables belong to one VariableSet:

Variable editing

The variable set resource supports GET and PUT operations. The idea is that you GET the variable set, make changes (add, modify, delete variables from the collection) then PUT it back.

VariableSets belong to a Project (or to a release, since we snapshot the variables each release). So you'll need the project in order to get the variable set.

Using Octopus.Client

Here's a complete example of using Octopus.Client:

var octopus = new OctopusRepository(new OctopusServerEndpoint("http://your-octopus", "API-YOURKEY"));

// Find the project that owns the variables we want to edit
var project = octopus.Projects.FindByName("My Project");

// Get the variables for editing
var variableSet = octopus.VariableSets.Get(project.Link("Variables"));

// Add a new variable
variableSet.Variables.Add(new VariableResource()
    Name = "ConnectionString",
    Value = "Server=(local);Database=Foo;trusted_connection=true",
    Scope = new ScopeSpecification()
        // Scope the variable to two environments using their environment ID
        { ScopeField.Environment, new ScopeValue("Environments-1", "Environments-2" )}

// Save the variables

What's happening

First, the client hits /api and gets back a document like this:

  "Application": "Octopus Deploy",
  "Version": "",
  "ApiVersion": "3.0.0",
  "Links": {
    "Projects": "/api/projects{/id}{?skip}",
    "Variables": "/api/variables{/id}"

Following the Projects link, we get a list of projects:

  "ItemType": "Project",
  "IsStale": false,
  "TotalResults": 7,
  "ItemsPerPage": 30,
  "Items": [
      "Id": "projects-65",
      "Name": "My Project",
      "VariableSetId": "variableset-projects-65",
      "Links": {
        "Self": "/api/projects/projects-65",
        "Releases": "/api/projects/projects-65/releases{/version}{?skip}",
        "Variables": "/api/variables/variableset-projects-65",
        "DeploymentProcess": "/api/deploymentprocesses/deploymentprocess-projects-65",
        "Web": "/app#/projects/projects-65"
      "Id": "projects-129",
      "Name": "My Project 2",
      "VariableSetId": "variableset-projects-129",

The Variables link on the project points us to the variable set resource:

  "Id": "variableset-projects-129",
  "OwnerId": "projects-129",
  "Variables": [
      "Id": "80bcaf5a-632a-470d-a8aa-a366f20c302e",
      "Name": "ConnectionString",
      "Value": "Server=(local);Database=Foo;trusted_connection=true",
      "Scope": {
        "Environment": [
      "IsSensitive": false,
      "IsEditable": true,
      "Prompt": null
  "ScopeValues": {
    "Environments": [
        "Id": "Environments-1",
        "Name": "Automation Testing"
        "Id": "Environments-34",
        "Name": "EC2 Production"
        "Id": "Environments-33",
        "Name": "EC2 Staging"
        "Id": "Environments-97",
        "Name": "Octopus"
        "Id": "Environments-2",
        "Name": "Release To Web"

We can now make changes to this resource, and PUT it back.

Note that the VariableSet document actually defines the different scope value options. In the UI we use this to populate the dropdowns when defining the scope. You could use this to map names like "EC2 Production" to "Environments-34" when setting scope options.

I hope that helps to provide both a sample of how to use the Octopus.Client API to modify variables, as well as to understand what is actually happening behind the scenes. Happy deployments!