Skip to content

Extending your Terraform configuration with the http provider

An example would be the 4.5.2 version of the Cloudflare Terraform provider w.r.t cloudflare_accounts resource (with no pagination, and the API defaults to 20 items)

# 1. Configure required providers
terraform {
required_providers {
http = {
source = "hashicorp/http"
version = "~> 3.0"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
variable "cloudflare_api_token" {
description = "Cloudflare API Token with Account Settings read permissions"
type = string
sensitive = true
}
# 3. Configure the Cloudflare provider (optional, only if using Cloudflare resources)
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
# 4. Fetch first page of accounts (50 per page)
data "http" "first_page" {
url = "https://api.cloudflare.com/client/v4/accounts?per_page=50"
request_headers = {
"Authorization" = "Bearer ${var.cloudflare_api_token}"
"Content-Type" = "application/json"
}
}
# 5. Parse response and calculate pagination
locals {
first_response = jsondecode(data.http.first_page.response_body)
# Check if request was successful
success = try(local.first_response.success, false)
first_results = local.success ? try(local.first_response.result, []) : []
total_pages = local.success ? try(local.first_response.result_info.total_pages, 1) : 0
# Create list of remaining pages (2, 3, 4, etc.)
remaining_pages = local.total_pages > 1 ? range(2, local.total_pages + 1) : []
}
# 6. Fetch remaining pages if needed
data "http" "remaining_pages" {
for_each = local.success ? toset([for p in local.remaining_pages : tostring(p)]) : toset([])
url = "https://api.cloudflare.com/client/v4/accounts?page=${each.value}&per_page=50"
request_headers = {
"Authorization" = "Bearer ${var.cloudflare_api_token}"
"Content-Type" = "application/json"
}
}
# 7. Combine all results
locals {
remaining_results = flatten([
for page in data.http.remaining_pages :
try(jsondecode(page.response_body).result, [])
])
# All accounts combined
all_accounts = concat(local.first_results, local.remaining_results)
# Create lookup maps for easy access
accounts_by_id = {
for acc in local.all_accounts : acc.id => acc
}
accounts_by_name = {
for acc in local.all_accounts : acc.name => acc
}
}
# 8. Outputs
output "success" {
description = "Whether the API calls were successful"
value = local.success
}
output "error" {
description = "Error message if authentication failed"
value = local.success ? null : try(local.first_response.errors[0].message, "Unknown error")
}
output "accounts" {
description = "All Cloudflare accounts"
value = local.all_accounts
}
output "account_ids" {
description = "List of all account IDs"
value = [for acc in local.all_accounts : acc.id]
}
output "account_names" {
description = "List of all account names"
value = [for acc in local.all_accounts : acc.name]
}
output "total_accounts" {
description = "Total number of accounts"
value = length(local.all_accounts)
}
# Create a zone in each account
resource "cloudflare_zone" "example" {
for_each = local.accounts_by_id
account_id = each.key
zone = "example-${replace(lower(each.value.name), " ", "-")}.com"
plan = "free"
type = "full"
}

Example 2: Access Specific Account by Name

Section titled “Example 2: Access Specific Account by Name”
# Get a specific account by name
locals {
production_account = try(local.accounts_by_name["Production"], null)
}
resource "cloudflare_zone" "prod_zone" {
count = local.production_account != null ? 1 : 0
account {
id = local.production_account.id
}
zone = "production.com"
plan = "enterprise"
}
# Filter accounts by name pattern
locals {
prod_accounts = {
for acc in local.all_accounts :
acc.id => acc
if strcontains(lower(acc.name), "prod")
}
# Filter by account type
enterprise_accounts = {
for acc in local.all_accounts :
acc.id => acc
if try(acc.type, "") == "enterprise"
}
}