Clusters
Clusters API methods, requests, and responses for RawTree Cloud and RawTree BYOC.
Clusters
Organization administrators can create, update, stop, resume, and delete clusters. Members can read cluster details.
Cluster endpoints require an authenticated user session or OAuth access token.
Pass the organization name as organization on every endpoint except the size
catalog. Organization members can read clusters and metrics; organization
admins are required to create, update, pause, resume, verify storage, or delete
clusters.
Cluster responses use this shape:
{
"id": "9f30c31c-74a7-4a08-aab0-494689ab5b31",
"name": "production",
"created_at": "2026-08-26 10:00:00+00",
"status": {
"phase": "ready",
"ready": true,
"message": null
},
"resources": {
"shards": 1,
"replicas": 2,
"cpu_cores_per_replica": 2.0,
"memory_bytes_per_replica": 8589934592,
"minimum_size": { "cpu_cores": 2.0, "memory_bytes": 8589934592 },
"maximum_size": { "cpu_cores": 64.0, "memory_bytes": 274877906944 }
},
"can_pause": true,
"can_resume": false,
"s3_storage": null,
"s3_storage_access": {
"external_id": "rawtree-5b71c457-7d83-474b-9db9-6dc48a1ec042",
"resource_tag": "rawtree-dc1fb78e-341d-48f8-a183-9ecea12eb41d"
},
"idle_timeout_minutes": 15
}resources can be null while resource information is unavailable. Use
status.ready, can_pause, and can_resume instead of inferring lifecycle
capabilities from the phase name.
s3_storage_access contains the saved, immutable external_id and resource_tag for this cluster's S3 storage access.
The object is null for older clusters without a saved identity.
resource_tag is the tag value for the fixed AWS tag key rawtree.com/cluster.
s3_storage is null for service-managed defaults, or contains data and
backups destinations for custom defaults. Both destinations always include
bucket and path in responses; an empty path means the bucket root. Responses do
not include the customer IAM role ARN.
GET /v1/clusters
List the organization's permanent clusters and their current status.
GET /v1/clusters?organization=acmeThe response contains an array of cluster objects:
{
"clusters": []
}Use an API key, a permitted workload token, or a user bearer token. Database-role keys support only the operations listed in Authentication.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | No | Organization name; required for users, optional for API keys |
Request:
# List permanent clusters and their current status.
curl -X GET "https://api.rawtree.com/v1/clusters" \
-H "Authorization: Bearer $RAWTREE_API_KEY"Expected response: HTTP 200.
{
"clusters": [
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "production",
"created_at": "2026-11-09T10:00:00Z",
"status": {
"phase": "ready",
"ready": true,
"label": "Ready",
"message": null
},
"can_pause": true,
"can_resume": false,
"idle_timeout_minutes": 30
}
]
}Errors: 400, 401, 403. See API errors.
GET /v1/clusters/{cluster_id}
Get one cluster by the UUID returned from the cluster list.
GET /v1/clusters/9f30c31c-74a7-4a08-aab0-494689ab5b31?organization=acmeUse a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
Request:
# Get a permanent cluster and its current status.
curl -X GET "https://api.rawtree.com/v1/clusters/33333333-3333-4333-8333-333333333333?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN"Expected response: HTTP 200.
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "production",
"created_at": "2026-11-09T10:00:00Z",
"status": {
"phase": "ready",
"ready": true,
"label": "Ready",
"message": null
},
"can_pause": true,
"can_resume": false,
"idle_timeout_minutes": 30
}Errors: 401, 403, 404. See API errors.
GET /v1/clusters/sizes
List the supported per-replica resource sizes, replica limits, and default
autoscaling bounds. Call this endpoint before creating a cluster and pass one
of its cpu_cores and memory_gib pairs back to the create endpoint.
{
"min_number_of_replicas": 1,
"max_number_of_replicas": 2,
"sizes": [
{ "size": "large", "cpu_cores": 2, "memory_gib": 8 },
{ "size": "xlarge", "cpu_cores": 4, "memory_gib": 16 }
],
"default_min_size": { "size": "large", "cpu_cores": 2, "memory_gib": 8 },
"default_max_size": { "size": "xlarge", "cpu_cores": 4, "memory_gib": 16 }
}The size label is for display. The resource pair is the stable create input.
Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Request:
# List cluster sizes and replica limits.
curl -X GET "https://api.rawtree.com/v1/clusters/sizes?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN"Expected response: HTTP 200.
{
"min_number_of_replicas": 1,
"max_number_of_replicas": 1,
"sizes": [
{
"size": "2 CPU / 8 GiB",
"cpu_cores": 2,
"memory_gib": 8
}
],
"default_min_size": {
"size": "2 CPU / 8 GiB",
"cpu_cores": 2,
"memory_gib": 8
},
"default_max_size": {
"size": "2 CPU / 8 GiB",
"cpu_cores": 2,
"memory_gib": 8
}
}Errors: 401. See API errors.
POST /v1/clusters
Create a cluster. name, region_id, replicas, and size are required.
Choose region_id from GET /v1/regions.
The API resolves the deployment. Callers do not need a deployment ID or routing headers.
The API rejects missing or null region IDs. Disabled regions and regions without a usable deployment cannot create clusters. The API does not select another region.
s3_storage_access is optional. Omit it, pass null, or omit either of its
external_id and resource_tag fields to let the API generate the missing values
as independent rawtree-<UUID> identities. Custom s3_storage requires an
explicit s3_storage_access.external_id matching the IAM trust policy. autoscaling,
idle_timeout_minutes, and s3_storage are optional.
POST /v1/clusters?organization=acme{
"name": "production",
"region_id": "11111111-1111-4111-8111-111111111111",
"replicas": 2,
"size": { "cpu_cores": 2, "memory_gib": 8 },
"autoscaling": {
"min_size": { "cpu_cores": 2, "memory_gib": 8 },
"max_size": { "cpu_cores": 8, "memory_gib": 32 }
},
"idle_timeout_minutes": 15
}Set idle_timeout_minutes to 0 to disable automatic idling, or use a value
from 15 through 43,200 minutes. Omit it to use the configured default. When
autoscaling is omitted, the size catalog's default_min_size and
default_max_size are used. The initial size must fall within those bounds.
To use customer-owned S3 storage, include s3_storage:
{
"name": "production",
"region_id": "11111111-1111-4111-8111-111111111111",
"replicas": 2,
"size": {
"cpu_cores": 2,
"memory_gib": 8
},
"s3_storage_access": {
"external_id": "rawtree-5b71c457-7d83-474b-9db9-6dc48a1ec042",
"resource_tag": "rawtree-dc1fb78e-341d-48f8-a183-9ecea12eb41d"
},
"s3_storage": {
"data": { "bucket": "acme-rawtree-data", "path": "rawtree/data" },
"backups": { "bucket": "acme-rawtree-backups", "path": "rawtree/backups" },
"role_arn": "arn:aws:iam::123456789012:role/RawTreeS3Access"
}
}Tables created normally use the cluster's configured storage. If cluster creation returns an ambiguous response, list clusters and look for the requested name before retrying.
Omit s3_storage or set it to null to use service-managed cluster defaults.
A custom s3_storage requires both data and backups, each with a bucket, plus
role_arn. Paths are optional and default to the bucket root. The two buckets
cannot be configured independently as custom and managed storage.
The API generates and saves missing identity values once at cluster creation.
Clients may supply explicit values when preparing IAM policies; the dashboard
keeps the values shown during setup when you switch storage modes. Read the
saved identity from s3_storage_access in the cluster response. Use the External ID in the
customer IAM role's trust policy. resource_tag contains the value for the fixed
AWS tag key rawtree.com/cluster. For custom database storage, apply
rawtree.com/cluster=<resource_tag> to both buckets and the customer IAM role.
These identity values cannot be changed after cluster creation. Top-level
external_id, resource_tag, and the old database_s3_access block are not accepted.
Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
name | body | string | Yes | — |
region_id | body | string | Yes | Region from /v1/regions. The API resolves its deployment internally. |
replicas | body | integer | Yes | — |
size | body | CreateClusterSize | Yes | Resources per replica, one of the sizes returned by /v1/clusters/sizes. |
idle_timeout_minutes | body | integer or null | No | Minutes without activity before automatically pausing. Omit to use the configured default. |
cluster_id | body | string or null | No | Optional client-generated cluster UUID. Omit to let the backend generate one. |
autoscaling | body | null or CreateClusterAutoscaling | No | — |
s3_storage | body | null or S3StorageInput | No | — |
s3_storage_access | body | null or S3StorageAccessInput | No | — |
Request:
# Create a permanent cluster.
curl -X POST "https://api.rawtree.com/v1/clusters?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "production",
"region_id": "11111111-1111-4111-8111-111111111111",
"replicas": 2,
"size": {
"cpu_cores": 2,
"memory_gib": 8
}
}'Expected response: HTTP 200.
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "production",
"created_at": "2026-11-09T10:00:00Z",
"status": {
"phase": "unknown",
"ready": false,
"label": "Unknown",
"message": null
},
"can_pause": false,
"can_resume": false,
"idle_timeout_minutes": 30
}Errors: 400, 401, 403. See API errors.
POST /v1/clusters/verify-s3-access
Verify that the service can assume the configured role and access both S3
destinations before creating the cluster. The s3_storage object has the same shape
as the create request. This pre-creation check also requires the proposed
s3_storage_access.external_id because the cluster has no saved identity yet.
Verification does not save it.
POST /v1/clusters/verify-s3-access?organization=acme{
"s3_storage_access": {
"external_id": "rawtree-5b71c457-7d83-474b-9db9-6dc48a1ec042"
},
"s3_storage": {
"data": { "bucket": "acme-rawtree-data", "path": "rawtree/data" },
"backups": { "bucket": "acme-rawtree-backups", "path": "rawtree/backups" },
"role_arn": "arn:aws:iam::123456789012:role/RawTreeS3Access"
}
}{ "verified": true, "message": "S3 access verified." }Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
s3_storage_access | body | S3StorageAccessInput | Yes | The proposed identity; external_id must match the customer IAM trust policy. |
s3_storage | body | S3StorageInput | Yes | — |
Request:
# Verify customer-owned S3 access for cluster creation.
curl -X POST "https://api.rawtree.com/v1/clusters/verify-s3-access?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"s3_storage_access": {
"external_id": "rawtree-docs-example",
"resource_tag": "33333333-3333-4333-8333-333333333333"
},
"s3_storage": {
"data": {
"bucket": "acme-rawtree-data",
"path": "rawtree/data"
},
"backups": {
"bucket": "acme-rawtree-backups",
"path": "rawtree/backups"
},
"role_arn": "arn:aws:iam::123456789012:role/RawTreeS3Access"
}
}'Expected response: HTTP 200.
{
"verified": true,
"message": "S3 access verified."
}Errors: 400, 401, 403. See API errors.
PATCH /v1/clusters/{cluster_id}
Update the cluster name, automatic idle timeout, or both. Omitted properties are unchanged.
PATCH /v1/clusters/9f30c31c-74a7-4a08-aab0-494689ab5b31?organization=acme{
"name": "primary",
"idle_timeout_minutes": 60
}Use idle_timeout_minutes: 0 to disable automatic idling.
Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
name | body | string or null | No | — |
idle_timeout_minutes | body | integer or null | No | — |
Request:
# Update cluster settings.
curl -X PATCH "https://api.rawtree.com/v1/clusters/33333333-3333-4333-8333-333333333333?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"idle_timeout_minutes": 30
}'Expected response: HTTP 200.
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "production",
"created_at": "2026-11-09T10:00:00Z",
"status": {
"phase": "unknown",
"ready": false,
"label": "Unknown",
"message": null
},
"can_pause": false,
"can_resume": false,
"idle_timeout_minutes": 30
}Errors: 400, 401, 403, 404. See API errors.
POST /v1/clusters/{cluster_id}/stop
Request that a running cluster pause. The response is the updated cluster
object; use its status and can_pause/can_resume fields to follow the
transition.
Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
Request:
# Stop a cluster.
curl -X POST "https://api.rawtree.com/v1/clusters/33333333-3333-4333-8333-333333333333/stop?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN"Expected response: HTTP 200.
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "production",
"created_at": "2026-11-09T10:00:00Z",
"status": {
"phase": "unknown",
"ready": false,
"label": "Unknown",
"message": null
},
"can_pause": false,
"can_resume": false,
"idle_timeout_minutes": 30
}Errors: 400, 401, 403, 404, 409. See API errors.
POST /v1/clusters/{cluster_id}/resume
Request that a paused cluster resume. The response is the updated cluster
object. A conflicting lifecycle transition returns 409.
Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
Request:
# Resume a cluster.
curl -X POST "https://api.rawtree.com/v1/clusters/33333333-3333-4333-8333-333333333333/resume?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN"Expected response: HTTP 200.
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "production",
"created_at": "2026-11-09T10:00:00Z",
"status": {
"phase": "unknown",
"ready": false,
"label": "Unknown",
"message": null
},
"can_pause": false,
"can_resume": false,
"idle_timeout_minutes": 30
}Errors: 400, 401, 403, 404, 409. See API errors.
DELETE /v1/clusters/{cluster_id}
Permanently delete a cluster.
{ "deleted": true }Use a user session or user OAuth token with full_access. API keys and workload tokens cannot use this method.
Parameters:
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
organization | query | string | Yes | Organization name |
Request:
# Permanently delete a cluster.
curl -X DELETE "https://api.rawtree.com/v1/clusters/33333333-3333-4333-8333-333333333333?organization=team_alpha" \
-H "Authorization: Bearer $RAWTREE_USER_TOKEN"Expected response: HTTP 200.
{
"deleted": true
}Errors: 400, 401, 403, 404. See API errors.