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.
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| 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
| Field | Type | Required | Description |
|---|---|---|---|
| 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
OKRequest succeeded. Response body contains the requested data.
-
201
CreatedNode successfully created. Returns the new node object with
status: "provisioning". -
202
AcceptedRequest accepted for async processing (restart, scaling). Poll for completion.
-
204
No ContentNode deletion initiated successfully. No response body.
-
400
Bad RequestInvalid parameters, malformed JSON, or missing required fields.
-
401
UnauthorizedMissing or invalid API key. Check your
Authorizationheader. -
403
ForbiddenAPI key lacks permission for this operation (e.g., read-only key trying to create).
-
404
Not FoundThe specified node ID does not exist or has already been deleted.
-
422
Unprocessable EntityValidation error — e.g., node name already in use, invalid region, or exceeded node limit.
-
429
Too Many RequestsRate limit exceeded. See the
Retry-Afterheader for when to retry. -
500
Internal Server ErrorUnexpected server error. Contact support if the issue persists.
-
503
Service UnavailableGeoServer 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"