API Overview
The Circloud API allows you to programmatically manage your VPCs, subnets, pods, and tunnels.
X-Auth-Token; admin endpoints use X-Admin-Token.
Authentication
Include your tenant API token in every request:
curl -k -X GET https://api.circloud.net/vpcs \ -H "X-Auth-Token: YOUR_API_TOKEN"
Admin endpoints require an admin token:
curl -k -X GET https://api.circloud.net/tenants \ -H "X-Admin-Token: YOUR_ADMIN_TOKEN"
Many create endpoints also accept a token field in the JSON body. The header is still required
and is the primary authentication check.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| username* | string | Yes | - | Admin username |
| password* | string | Yes | - | Admin password |
Response
200 Admin user with api_token
Tenant Endpoints (Admin)
Manage tenant lifecycle and retrieve full tenant topology. Requires X-Admin-Token.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| name* | string | Yes | - | Tenant name (DNS-compliant) |
| description | string | No | null | Optional description |
| password* | string | Yes | - | Login password for tenant GUI |
Response
200 Array of tenants
Response
200 Tenant object with VPCs, pods, tunnels, and pod status
Response
204 Tenant deleted (cascades to all resources)
Domain Endpoints (Admin)
Assign custom domains to tenants for tunnel usage.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| domain* | string | Yes | - | Domain name (e.g., example.com) |
Response
200 Array of domains
Provider Config (Admin)
Configure external subnet, DNS, and Cloudflare credentials.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| external_subnet_cidr* | string | Yes | - | External subnet CIDR |
| external_subnet_gateway* | string | Yes | - | Gateway for external subnet |
| peering_subnet_cidr* | string | Yes | - | Peering subnet for core services |
| pod_dns_nameservers | array | No | [] | External DNS resolvers |
| pod_dns_ndots | integer | No | null | DNS ndots setting |
| cloudflare_account_id | string | No | null | Cloudflare account ID |
| cloudflare_api_token | string | No | null | Cloudflare API token |
| cloudflare_domain | string | No | null | Default tunnel domain |
Response
200 Provider configuration
VPC Endpoints
Create and manage Virtual Private Clouds.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| tenant_id* | string | Yes | - | Your tenant UUID |
| token* | string | Yes | - | Your API token |
| name* | string | Yes | - | VPC name (DNS-compliant) |
| enable_internet* | boolean | Yes | - | Enable internet access |
Example
curl -k -X POST https://api.circloud.net/vpcs \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "YOUR_TENANT_ID",
"token": "YOUR_TOKEN",
"name": "production",
"enable_internet": true
}'
Response
200 Array of VPCs
Response
204 VPC deleted (cascades to subnets and pods)
Subnet Endpoints
Create and manage subnets within VPCs.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| tenant_id* | string | Yes | - | Your tenant UUID |
| token* | string | Yes | - | Your API token |
| vpc_id* | string | Yes | - | Parent VPC UUID |
| name* | string | Yes | - | Subnet name |
| cidr* | string | Yes | - | CIDR block (e.g., "10.100.1.0/24") |
| gateway_ip* | string | Yes | - | Gateway IP within CIDR |
Example
curl -k -X POST https://api.circloud.net/subnets \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "YOUR_TENANT_ID",
"token": "YOUR_TOKEN",
"vpc_id": "VPC_ID",
"name": "web-tier",
"cidr": "10.100.1.0/24",
"gateway_ip": "10.100.1.1"
}'
Response
200 Array of subnets
Pod Endpoints
Deploy and manage containerized workloads.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| tenant_id* | string | Yes | - | Your tenant UUID |
| token* | string | Yes | - | Your API token |
| vpc_id* | string | Yes | - | Target VPC UUID |
| subnet_id* | string | Yes | - | Target subnet UUID |
| name* | string | Yes | - | Pod name (DNS-compliant) |
| container_image* | string | Yes | - | Container image (e.g., "nginx:latest") |
| replica_count | integer | No | 1 | Replica count (1-10). If auto_scaling is true, this is the initial replica count (min 2) |
| service_port | integer | No | 80 | VIP service port (default 80) |
| use_registry_credentials | boolean | No | true | Use tenant registry secret for image pulls |
| external_access | boolean | No | false | Enable outbound internet (SNAT) |
| external_inbound | boolean | No | false | Enable inbound with external IP (requires external_access) |
| auto_healing | boolean | No | false | Auto-restart on failure |
| auto_scaling | boolean | No | false | Enable autoscaling with HPA (CPU-based) |
| autoscale_max_replicas | integer | No | 10 | Maximum replicas when autoscaling (default 10) |
| autoscale_cpu_target_millicores | integer | No | 200 | Target average CPU usage per pod in millicores (default 200) |
| tunnels | array | No | [] | Inline tunnel definitions for this pod |
Notes: For replicas, Circloud creates one VIP service that load-balances across all replicas.
Auto-scaling creates an HPA (auto_healing is implied), and the minimum replica count is always 2.
Live status data is available in the admin /tenants/{tenant_id} response.
Example
curl -k -X POST https://api.circloud.net/pods \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "YOUR_TENANT_ID",
"token": "YOUR_TOKEN",
"vpc_id": "VPC_ID",
"subnet_id": "SUBNET_ID",
"name": "web-server",
"container_image": "nginx:latest",
"replica_count": 2,
"service_port": 80,
"external_access": true,
"external_inbound": true,
"auto_scaling": true,
"autoscale_max_replicas": 6,
"autoscale_cpu_target_millicores": 250
}'
Response
200 Pod object with updated replica_count
Note: Adds a single replica and updates the logical pod's replica_count. Not available when auto_scaling is enabled.
Response
200 Pod object with updated replica_count
Note: Removes a single replica (minimum 1). Not available when auto_scaling is enabled.
Response
200 Pod restart initiated
Response
200 Array of pods with status
Response
204 Pod deleted
Tunnel Endpoints
Create Cloudflare tunnels for secure external access via Cloudflare's global network.
Supported Protocols
| Protocol | Use Cases | How to Connect |
|---|---|---|
| http | Web apps, REST APIs, webhooks | Browser: https://subdomain.domain.com |
| https | End-to-end encryption, mTLS | Browser: https://subdomain.domain.com |
| ssh | Remote terminal, SFTP, Git | cloudflared access ssh --hostname host |
| tcp | Databases (PostgreSQL, MySQL, Redis) | cloudflared access tcp --hostname host |
| udp | Game servers, VoIP, DNS | Direct: hostname:port |
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| tunnel_name* | string | Yes | - | Unique tunnel name |
| subdomain* | string | Yes | - | Subdomain for access |
| protocol_type* | string | Yes | - | http, https, ssh, tcp, udp |
| service_port | integer | No | 80 | Target port (default: 80) |
| domain | string | No | null | Custom domain (must be approved) |
HTTP Tunnel (Web Apps)
curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tunnel_name": "web-app",
"subdomain": "app",
"protocol_type": "http",
"service_port": 80
}'
# Access: https://app.yourdomain.com
SSH Tunnel (Remote Access)
curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tunnel_name": "ssh-access",
"subdomain": "ssh",
"protocol_type": "ssh",
"service_port": 22
}'
# Connect: cloudflared access ssh --hostname ssh.yourdomain.com
TCP Tunnel (Database)
curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tunnel_name": "database",
"subdomain": "db",
"protocol_type": "tcp",
"service_port": 5432
}'
# Connect: cloudflared access tcp --hostname db.yourdomain.com --url localhost:5432
# Then: psql -h localhost -p 5432 -U myuser mydb
UDP Tunnel (Game Server)
curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tunnel_name": "game-server",
"subdomain": "game",
"protocol_type": "udp",
"service_port": 27015
}'
# Connect directly: game.yourdomain.com:27015
Response
201 Tunnel created
{
"id": "tunnel-uuid",
"tunnel_name": "web-tunnel",
"hostname": "app.yourdomain.com",
"protocol_type": "http",
"status": "active"
}
Notes
Uses the pod ID query parameter and auto-derives the tunnel name from the pod.
Response
200 Array of tunnels for the pod
Response
200 Array of tunnels
Response
204 Tunnel deleted
Admin: POST /service-tunnels creates Cloudflare tunnels for platform services
(API, GUIs) using X-Admin-Token.
Registry Credentials
Manage private container registry credentials.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| name* | string | Yes | - | Registry name (e.g., "dockerhub") |
| server* | string | Yes | - | Registry server URL |
| username* | string | Yes | - | Registry username |
| password* | string | Yes | - | Registry password/token |
Example
curl -k -X POST https://api.circloud.net/tenants/YOUR_TENANT_ID/registry-credentials \
-H "X-Auth-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "dockerhub",
"server": "https://index.docker.io/v1/",
"username": "myusername",
"password": "mytoken"
}'
Response
200 Array of credentials (passwords hidden)
Response
200 Credential deleted
Topology API
Deploy complete infrastructure in a single API call.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| token* | string | Yes | - | Your API token |
| vpcs* | array | Yes | - | Array of VPC definitions |
| subnets* | array | Yes | - | Array of subnet definitions |
| pods | array | No | [] | Array of pod definitions |
Example
curl -k -X POST https://api.circloud.net/tenants/TENANT_ID/topology \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_TOKEN",
"vpcs": [
{"name": "production", "enable_internet": true}
],
"subnets": [
{
"name": "web",
"vpc_name": "production",
"cidr": "10.100.1.0/24",
"gateway_ip": "10.100.1.1"
}
],
"pods": [
{
"name": "nginx",
"vpc_name": "production",
"subnet_name": "web",
"container_image": "nginx:latest",
"replica_count": 2,
"service_port": 80,
"auto_scaling": true,
"autoscale_max_replicas": 6,
"autoscale_cpu_target_millicores": 250
}
]
}'
Response
200 Current topology as JSON
Health & Version
Check API health and version information.
curl -k https://api.circloud.net/healthz curl -k https://api.circloud.net/version
Error Handling
All errors return a JSON response with a detail field.
| Status Code | Description |
|---|---|
| 200 | Request succeeded |
| 201 | Resource created |
| 204 | Resource deleted |
| 400 | Invalid parameters |
| 401 | Invalid token |
| 404 | Resource not found |
| 409 | Resource conflict |
{"detail": "Error message describing what went wrong"}
Support
Support the Circloud project with a donation.
Support Circloud Project
Donate