Terraform Cloud API
Introduction
The Terraform Cloud API provides a programmatic interface to Terraform Cloud, allowing you to automate and integrate your infrastructure management workflows with other tools and systems. This API follows REST principles and uses JSON for data formatting, making it accessible from virtually any programming language or automation tool.
Whether you need to create workspaces, manage variables, trigger runs, or retrieve state data, the Terraform Cloud API gives you the flexibility to interact with all aspects of Terraform Cloud programmatically rather than through the web interface.
API Basics
Authentication
Before making any API requests, you'll need to authenticate. Terraform Cloud API supports authentication using tokens:
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
https://app.terraform.io/api/v2/organizations
You can generate API tokens in two ways:
- User tokens: Created in your user settings, these tokens have the same permissions as your user account
- Team tokens: Associated with a specific team in your organization, with that team's permissions
API URL Structure
The Terraform Cloud API follows a consistent URL structure:
https://app.terraform.io/api/v2/{resource}/{resource_id}/{sub-resource}
For example:
- List all workspaces:
https://app.terraform.io/api/v2/organizations/{org_name}/workspaces
- Get workspace details:
https://app.terraform.io/api/v2/workspaces/{workspace_id}
Request and Response Format
The API uses JSON API specification for both requests and responses:
# Request example
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request GET \
https://app.terraform.io/api/v2/organizations/my-organization/workspaces
Response example:
{
"data": [
{
"id": "ws-cZE9LERN34XuzWjr",
"type": "workspaces",
"attributes": {
"name": "my-workspace",
"created-at": "2020-05-12T15:48:00.000Z",
"terraform-version": "0.12.24"
// more attributes...
}
}
// more workspaces...
]
}
Common API Operations
Let's explore some common operations you might perform with the Terraform Cloud API.
Managing Workspaces
Create a Workspace
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @payload.json \
https://app.terraform.io/api/v2/organizations/my-organization/workspaces
With payload.json
containing:
{
"data": {
"type": "workspaces",
"attributes": {
"name": "my-new-workspace",
"terraform-version": "1.0.0",
"description": "Created via API"
}
}
}
Response:
{
"data": {
"id": "ws-SihZTyXKfNXUWuUa",
"type": "workspaces",
"attributes": {
"name": "my-new-workspace",
"terraform-version": "1.0.0",
"description": "Created via API"
// more attributes...
}
}
}
List All Workspaces
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request GET \
https://app.terraform.io/api/v2/organizations/my-organization/workspaces
Managing Variables
Variables in Terraform Cloud can be managed via API, which is especially useful for automation.
Create a Variable
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @var-payload.json \
https://app.terraform.io/api/v2/workspaces/ws-SihZTyXKfNXUWuUa/vars
With var-payload.json
containing:
{
"data": {
"type": "vars",
"attributes": {
"key": "database_password",
"value": "supersecret",
"category": "terraform",
"hcl": false,
"sensitive": true
}
}
}
Triggering Runs
One of the most common operations is triggering a Terraform run programmatically:
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @run-payload.json \
https://app.terraform.io/api/v2/runs
With run-payload.json
containing:
{
"data": {
"type": "runs",
"attributes": {
"message": "Run triggered via API"
},
"relationships": {
"workspace": {
"data": {
"type": "workspaces",
"id": "ws-SihZTyXKfNXUWuUa"
}
}
}
}
}
Practical Examples
Let's walk through some practical examples that demonstrate how to use the Terraform Cloud API in real-world scenarios.
Example 1: Automating Workspace Creation in CI/CD
This example shows how to create a workspace automatically as part of a CI/CD pipeline:
#!/bin/bash
# Input parameters
ORG_NAME="my-organization"
WORKSPACE_NAME="project-${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}"
TERRAFORM_VERSION="1.1.0"
# Create JSON payload
cat > payload.json << EOF
{
"data": {
"type": "workspaces",
"attributes": {
"name": "${WORKSPACE_NAME}",
"terraform-version": "${TERRAFORM_VERSION}",
"description": "Auto-created by CI for ${CI_PROJECT_NAME}",
"auto-apply": true
}
}
}
EOF
# Send API request
curl \
--header "Authorization: Bearer ${TF_API_TOKEN}" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @payload.json \
https://app.terraform.io/api/v2/organizations/${ORG_NAME}/workspaces
# Clean up
rm payload.json
Example 2: Retrieving State Data
This example demonstrates how to extract state data for integration with other systems:
import requests
import json
# Configuration
api_token = "YOUR_API_TOKEN"
org_name = "my-organization"
workspace_name = "production-infrastructure"
# Set up headers
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/vnd.api+json"
}
# Get workspace ID
workspace_url = f"https://app.terraform.io/api/v2/organizations/{org_name}/workspaces/{workspace_name}"
workspace_response = requests.get(workspace_url, headers=headers)
workspace_data = workspace_response.json()
workspace_id = workspace_data["data"]["id"]
# Get current state version
state_url = f"https://app.terraform.io/api/v2/workspaces/{workspace_id}/current-state-version"
state_version_response = requests.get(state_url, headers=headers)
state_version_data = state_version_response.json()
state_file_url = state_version_data["data"]["attributes"]["hosted-state-download-url"]
# Download state file
state_response = requests.get(state_file_url)
state_data = state_response.json()
# Now you can extract and use specific outputs
outputs = state_data["outputs"]
print(f"Database endpoint: {outputs['db_endpoint']['value']}")
print(f"Load balancer address: {outputs['lb_address']['value']}")
Example 3: Setting Multiple Variables at Once
This Python script demonstrates how to set multiple variables for a workspace:
import requests
import json
# Configuration
api_token = "YOUR_API_TOKEN"
workspace_id = "ws-SihZTyXKfNXUWuUa"
# Variables to set
variables = [
{"key": "region", "value": "us-west-2", "category": "terraform", "sensitive": False},
{"key": "environment", "value": "staging", "category": "terraform", "sensitive": False},
{"key": "db_username", "value": "admin", "category": "terraform", "sensitive": False},
{"key": "db_password", "value": "super-secret-password", "category": "terraform", "sensitive": True}
]
# Set up headers
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/vnd.api+json"
}
# Create each variable
for var in variables:
payload = {
"data": {
"type": "vars",
"attributes": {
"key": var["key"],
"value": var["value"],
"category": var["category"],
"sensitive": var["sensitive"]
}
}
}
response = requests.post(
f"https://app.terraform.io/api/v2/workspaces/{workspace_id}/vars",
headers=headers,
data=json.dumps(payload)
)
if response.status_code == 201:
print(f"Successfully created variable {var['key']}")
else:
print(f"Failed to create variable {var['key']}: {response.text}")
API Workflow Visualization
Here's a diagram showing the typical workflow when using the Terraform Cloud API:
Advanced API Features
Configuring Workspace Settings
The API allows you to configure almost all workspace settings:
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request PATCH \
--data @settings-payload.json \
https://app.terraform.io/api/v2/workspaces/ws-SihZTyXKfNXUWuUa
With settings-payload.json
containing:
{
"data": {
"type": "workspaces",
"id": "ws-SihZTyXKfNXUWuUa",
"attributes": {
"terraform-version": "1.1.5",
"auto-apply": true,
"execution-mode": "remote",
"working-directory": "environments/staging"
}
}
}
Managing Team Access
You can programmatically manage team access to workspaces:
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @team-access-payload.json \
https://app.terraform.io/api/v2/team-workspaces
With team-access-payload.json
containing:
{
"data": {
"type": "team-workspaces",
"attributes": {
"access": "write"
},
"relationships": {
"workspace": {
"data": {
"type": "workspaces",
"id": "ws-SihZTyXKfNXUWuUa"
}
},
"team": {
"data": {
"type": "teams",
"id": "team-L5DuCjPVHXqS9xMj"
}
}
}
}
}
Error Handling
When working with the API, you'll need to handle various error responses:
{
"errors": [
{
"status": "422",
"title": "invalid attribute",
"detail": "Workspace name must be unique within the organization"
}
]
}
Best practices for error handling:
- Always check response status codes
- Parse the error object for specific details
- Implement appropriate retry logic for transient errors
- Log detailed error information for debugging
API Rate Limiting
Terraform Cloud implements rate limiting to prevent API abuse. Current limits:
- 30 requests per second per IP address
- Additional organization-based rate limits may apply
If you exceed the rate limit, you'll receive a 429 Too Many Requests
response. The response headers include:
X-RateLimit-Limit
: Maximum number of requests allowedX-RateLimit-Remaining
: Number of requests remaining in the current windowRetry-After
: Seconds to wait before making another request
Summary
The Terraform Cloud API provides a powerful way to automate your infrastructure management workflows:
- Create and manage workspaces programmatically
- Configure variables securely
- Trigger and monitor Terraform runs
- Retrieve state data for integration with other systems
- Manage team access and permissions
By leveraging this API, you can integrate Terraform Cloud with your existing CI/CD pipelines, create custom dashboards, implement advanced automation, and much more.
Additional Resources
Exercises
- Create a script that generates a new workspace with predefined variables for each branch in your repository.
- Write a program that extracts outputs from Terraform state and updates DNS records in your domain provider.
- Build a simple dashboard that shows the status of all your Terraform runs across different workspaces.
- Create a notification system that sends alerts when Terraform plan shows infrastructure changes.
- Implement a script that compares variables across different workspaces to ensure consistency.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)