# Thin wrapper for the Cloudflare API (Bearer token). # Mirrors coolify_skill/scripts/Invoke-CoolifyApi.ps1. # Requires CLOUDFLARE_API_TOKEN (load from .env.local.ps1). # Optional: CLOUDFLARE_API_URL (defaults to the public Cloudflare v4 base). # Useful IDs to keep in env: CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_ZONE_ID, CLOUDFLARE_TUNNEL_ID. # # Examples: # .\scripts\Invoke-CloudflareApi.ps1 -Path "/user/tokens/verify" # .\scripts\Invoke-CloudflareApi.ps1 -Path "/accounts/$($env:CLOUDFLARE_ACCOUNT_ID)/cfd_tunnel/$($env:CLOUDFLARE_TUNNEL_ID)/configurations" # .\scripts\Invoke-CloudflareApi.ps1 -Method PUT -Path "/accounts/.../cfd_tunnel/.../configurations" -BodyJson $body param( [ValidateSet("GET", "POST", "PUT", "PATCH", "DELETE")] [string]$Method = "GET", [Parameter(Mandatory = $true)] [string]$Path, [string]$BodyJson, [switch]$Raw ) $ErrorActionPreference = "Stop" $baseUrl = if ($env:CLOUDFLARE_API_URL) { $env:CLOUDFLARE_API_URL } else { "https://api.cloudflare.com/client/v4" } if ([string]::IsNullOrWhiteSpace($env:CLOUDFLARE_API_TOKEN)) { throw "Set CLOUDFLARE_API_TOKEN before calling the Cloudflare API." } $baseUrl = $baseUrl.TrimEnd("/") $cleanPath = if ($Path.StartsWith("/")) { $Path } else { "/$Path" } $uri = "$baseUrl$cleanPath" $headers = @{ Authorization = "Bearer $($env:CLOUDFLARE_API_TOKEN)" Accept = "application/json" } $request = @{ Method = $Method Uri = $uri Headers = $headers TimeoutSec = 30 } if ($PSBoundParameters.ContainsKey("BodyJson")) { try { $null = $BodyJson | ConvertFrom-Json } catch { throw "BodyJson is not valid JSON: $($_.Exception.Message)" } $request.Body = $BodyJson $request.ContentType = "application/json" } try { $response = Invoke-RestMethod @request } catch { throw "Cloudflare API request failed: $($_.Exception.Message)" } if ($Raw) { $response } else { $response | ConvertTo-Json -Depth 50 }