GET POST PUT DELETE

/api/nodes

Manage GeoServer compute nodes — the distributed servers that handle map rendering, spatial queries, and data streaming. Create, configure, scale, and monitor nodes across your geospatial infrastructure.

🔑

Authentication Required

All node endpoints require a valid API key. Include your key in the Authorization: Bearer <token> header. Learn more →

GET /api/nodes List all nodes

Query Parameters

Parameter Type Required Default Description
region string No Filter nodes by deployment region (e.g., us-east-1, eu-west-2)
status string No Filter by node status: active, provisioning, degraded, offline
type string No Filter by node type: renderer, analytics, stream, hybrid
page integer No 1 Page number for paginated results
per_page integer No 20 Results per page (max: 100)
sort string No created_at Sort field: created_at, name, status, cpu_usage
order string No desc Sort direction: asc or desc

Example Request

cURL
curl https://api.geoserver.io/v2/api/nodes \
  -H "Authorization: Bearer sk_live_abc123..." \
  -H "Accept: application/json" \
  --data-urlencode "status=active" \
  --data-urlencode "region=us-east-1"

Example Response (200 OK)

JSON
{
  "data: [
    {
      "id: "node_8xK2mPqR9vLw",
      "name: "renderer-prod-01,
      "type: "renderer",
      "region: "us-east-1",
      "status: "active",
      "tier: "large",
      "cpu_usage: 67.3,
      "memory_usage: 14.2,
      "memory_total_gb: 32,
      "layers_count: 142,
      "requests_per_min: 1847,
      "avg_response_ms: 23.4,
      "created_at: "2024-11-15T08:30:00Z",
      "last_heartbeat: "2025-01-20T14:22:01Z",
      "public_ip: "54.213.89.42",
      "tags: ["production", "tile-serving"]
    },
    {
      "id: "node_3bN7jTqY5mZp",
      "name: "analytics-prod-02,
      "type: "analytics",
      "region: "us-east-1",
      "status: "active",
      "tier: "xlarge",
      "cpu_usage: 42.1,
      "memory_usage: 28.7,
      "memory_total_gb: 64,
      "layers_count: 89,
      "requests_per_min: 523,
      "avg_response_ms: 145.2,
      "created_at: "2024-12-01T12:00:00Z",
      "last_heartbeat: "2025-01-20T14:21:58Z",
      "public_ip: "54.213.90.17",
      "tags: ["production", "spatial-queries"]
    }
  ],
  "pagination: {
    "page: 1,
    "per_page: 20,
    "total: 12,
    "total_pages: 1
  }
}
GET /api/nodes/:id Get a single node

Path Parameters

Parameter Type Required Description
id string Yes The unique node identifier (e.g., node_8xK2mPqR9vLw)

Example Request

curl https://api.geoserver.io/v2/api/nodes/node_8xK2mPqR9vLw \
  -H "Authorization: Bearer sk_live_abc123..."

Response (200 OK)

JSON
{
  "id: "node_8xK2mPqR9vLw",
  "name: "renderer-prod-01",
  "type: "renderer",
  "region: "us-east-1",
  "status: "active",
  "tier: "large",
  "cpu_usage: 67.3,
  "memory_usage: 14.2,
  "memory_total_gb: 32,
  "disk_used_gb: 847,
  "disk_total_gb: 2000,
  "layers_count: 142,
  "requests_per_min: 1847,
  "avg_response_ms: 23.4,
  "uptime_hours: 624,
  "created_at: "2024-11-15T08:30:00Z",
  "last_heartbeat: "2025-01-20T14:22:01Z",
  "public_ip: "54.213.89.42",
  "private_ip: "10.0.4.112",
  "geoserver_version: "2.25.1",
  "java_version: "17.0.9",
  "tags: ["production", "tile-serving"],
  "config: {
    "max_threads: 64,
    "cache_size_mb: 4096,
    "wms_timeout_ms: 30000,
    "wfs_timeout_ms: 60000
  }
}
POST /api/nodes Create a new node

Request Body

Field Type Required Default Description
name string Yes Human-readable name for the node (3-64 chars)
type string Yes Node role: renderer, analytics, stream, hybrid
region string Yes Deployment region (e.g., us-east-1, eu-west-2, ap-southeast-1)
tier string No "medium" Compute tier: small, medium, large, xlarge, 2xlarge
auto_scale boolean No false Enable automatic scaling based on load
tags array No [] Array of tag strings for organization
config object No Optional GeoServer configuration overrides (max_threads, cache_size_mb, etc.)

Example Request

cURL
curl https://api.geoserver.io/v2/api/nodes \
  -X POST \
  -H "Authorization: Bearer sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "analytics-eu-03",
    "type": "analytics",
    "region": "eu-west-2",
    "tier": "xlarge",
    "auto_scale": true,
    "tags": ["europe", "spatial-analysis"],
    "config": {
      "max_threads": 128,
      "cache_size_mb": 8192
    }
  }'

Response (201 Created)

JSON
{
  "id: "node_5wQ8nRtK2mXp",
  "name: "analytics-eu-03",
  "type: "analytics",
  "region: "eu-west-2",
  "status: "provisioning",
  "tier: "xlarge",
  "auto_scale: true,
  "tags: ["europe", "spatial-analysis"],
  "config: {
    "max_threads: 128,
    "cache_size_mb: 8192
  },
  "created_at: "2025-01-20T14:30:00Z",
  "estimated_ready_at: "2025-01-20T14:35:00Z"
}
💡
Node provisioning typically takes 3–5 minutes. You can poll the GET /api/nodes/:id endpoint or use webhooks to receive a node.ready event when provisioning completes.
PUT /api/nodes/:id Update a node (full replacement)

Full replacement of the node resource. All fields must be provided. Use PATCH for partial updates.

Example Request

cURL
curl https://api.geoserver.io/v2/api/nodes/node_8xK2mPqR9vLw \
  -X PUT \
  -H "Authorization: Bearer sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "renderer-prod-01-updated",
    "type": "renderer",
    "region": "us-east-1",
    "tier": "xlarge",
    "auto_scale": true,
    "tags": ["production", "tile-serving", "v2"],
    "config": {
      "max_threads": 128,
      "cache_size_mb": 8192,
      "wms_timeout_ms": 45000
    }
  }'
PATCH /api/nodes/:id Partial update

Update only specific fields. Only include the fields you want to change.

Example Request

cURL
curl https://api.geoserver.io/v2/api/nodes/node_8xK2mPqR9vLw \
  -X PATCH \
  -H "Authorization: Bearer sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "tier": "xlarge",
    "tags": ["production", "tile-serving", "v2"]
  }'
DELETE /api/nodes/:id Delete a node
⚠️
Deleting a node is irreversible. All layers hosted exclusively on this node will become unavailable. Ensure data is replicated or migrated before deleting.

Query Parameters

ParameterTypeRequiredDescription
force boolean No Bypass confirmation and delete immediately. Use with caution.
migrate_layers string No ID of a target node to migrate all layers to before deletion.

Example Request

cURL
curl https://api.geoserver.io/v2/api/nodes/node_8xK2mPqR9vLw?migrate_layers=node_3bN7jTqY5mZp \
  -X DELETE \
  -H "Authorization: Bearer sk_live_abc123..."

Response (204 No Content)

No response body. The node is scheduled for deletion and will be fully removed within 2–3 minutes.

GET /api/nodes/:id/health Node health check

Example Response (200 OK)

JSON
{
  "status: "healthy",
  "checks: {
    "geoserver_process: { "status: "passing", "latency_ms: 2 },
    "postgres_connection: { "status: "passing", "latency_ms: 5 },
    "disk_space: { "status: "passing", "used_pct: 42.3 },
    "memory: { "status: "passing", "used_pct: 44.4 },
    "wms_endpoint: { "status: "passing", "latency_ms: 12 },
    "wfs_endpoint: { "status: "passing", "latency_ms: 8 },
    "tile_cache: { "status: "passing", "hit_rate: 0.94 }
  },
  "last_check_at: "2025-01-20T14:22:05Z",
  "uptime_hours: 624
}
POST /api/nodes/:id/restart Restart a node
⚠️
Restarting a node will cause a brief service interruption (15–30 seconds). Ensure the node is not the sole provider for critical layers.

Example Response (202 Accepted)

JSON
{
  "id: "node_8xK2mPqR9vLw",
  "status: "restarting",
  "message: "Node restart initiated. Expected completion in ~30 seconds.",
  "estimated_ready_at: "2025-01-20T14:23:00Z"
}
POST /api/nodes/scale Auto-scale nodes

Request Body

FieldTypeRequiredDescription
region string Yes Target region to scale in
type string Yes Node type to scale
count integer Yes Number of nodes to add (positive) or remove (negative)
tier string No Compute tier for new nodes (defaults to existing tier)

Example Request

cURL
curl https://api.geoserver.io/v2/api/nodes/scale \
  -X POST \
  -H "Authorization: Bearer sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "region": "us-east-1",
    "type": "renderer",
    "count": 3,
    "tier": "large"
  }'

Response (202 Accepted)

JSON
{
  "scaling_operation: "scale_op_7xR3mKpN2v",
  "status: "in_progress",
  "region: "us-east-1",
  "type: "renderer",
  "nodes_to_add: 3,
  "new_node_ids: [
    "node_9aM4pLqT6nYw",
    "node_2cF8hRsU3jZx",
    "node_6dG1kNwV5mPq"
  ],
  "estimated_completion_at: "2025-01-20T14:40:00Z"
}

Status Codes

  • 200
    OK
    Request succeeded. Response body contains the requested data.
  • 201
    Created
    Node successfully created. Returns the new node object with status: "provisioning".
  • 202
    Accepted
    Request accepted for async processing (restart, scaling). Poll for completion.
  • 204
    No Content
    Node deletion initiated successfully. No response body.
  • 400
    Bad Request
    Invalid parameters, malformed JSON, or missing required fields.
  • 401
    Unauthorized
    Missing or invalid API key. Check your Authorization header.
  • 403
    Forbidden
    API key lacks permission for this operation (e.g., read-only key trying to create).
  • 404
    Not Found
    The specified node ID does not exist or has already been deleted.
  • 422
    Unprocessable Entity
    Validation error — e.g., node name already in use, invalid region, or exceeded node limit.
  • 429
    Too Many Requests
    Rate limit exceeded. See the Retry-After header for when to retry.
  • 500
    Internal Server Error
    Unexpected server error. Contact support if the issue persists.
  • 503
    Service Unavailable
    GeoServer API is temporarily unavailable. Retry after a brief delay.

Rate Limiting

Node endpoints are subject to the following rate limits per API key:

120
Reads per minute
30
Writes per minute
5
Creates per minute
📊
Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Error Response Format

JSON
{
  "error: {
    "code: "node_not_found",
    "status: 404,
    "message: "No node found with ID 'node_invalid123'.",
    "request_id: "req_8xK2mPqR9vLw3bN7",
    "documentation_url: "https://docs.geoserver.io/api/errors#node_not_found"
  }
}

SDK Examples

JavaScript / Node.js

JavaScript
// Install: npm install @geoserver/sdk
const { GeoServer } = require("@geoserver/sdk");

const geo = new GeoServer({
  apiKey: process.env.GEOSERVER_API_KEY
});

// List all active nodes
const nodes = await geo.nodes.list({ status: "active" });
console.log(nodes.data);

// Create a new analytics node
const newNode = await geo.nodes.create({
  name: "analytics-eu-03",
  type: "analytics",
  region: "eu-west-2",
  tier: "xlarge"
});
console.log(newNode.id); // "node_5wQ8nRtK2mXp"

// Check node health
const health = await geo.nodes.health("node_8xK2mPqR9vLw");
console.log(health.status); // "healthy"

Python

Python
# Install: pip install geoserver-sdk
from geoserver import GeoServerClient

geo = GeoServerClient(api_key="sk_live_abc123...")

# List all active nodes
nodes = geo.nodes.list(status="active")
print(nodes["data"])

# Create a new renderer node
new_node = geo.nodes.create(
    name="renderer-prod-04",
    type="renderer",
    region="us-east-1",
    tier="large"
)
print(new_node["id"])

# Restart a node
result = geo.nodes.restart("node_8xK2mPqR9vLw")
print(result["status"])  # "restarting"