Write operations in the Gcore Cloud API are asynchronous — the API returns a task ID immediately, while the actual operation runs in the background. The created resource ID is only available after polling the task to completion.
This applies to every operation that changes infrastructure state: creating instances, volumes, networks, load balancers, Kubernetes clusters, and more.
- Make the request. A write call returns a task ID immediately:
{
"tasks": ["d4a4b10e-5d22-4c23-8e09-f7a3e1c1a999"]
}
- Poll the task. Call
GET /cloud/v1/tasks/{task_id} repeatedly until the state field is no longer RUNNING:
curl "https://api.gcore.com/cloud/v1/tasks/{TASK_ID}" \
-H "Authorization: APIKey $GCORE_API_KEY"
- Extract the result. When
state is FINISHED, find the created resource ID in created_resources.
Task states
Tasks move through four states from creation to completion:
| State | Meaning |
|---|
NEW | Task queued, not yet started |
RUNNING | Operation in progress |
FINISHED | Operation completed successfully |
ERROR | Operation failed — check error field |
Task response
A finished create_vm task response shows the complete structure, including the created_resources field where the new resource IDs are found:
{
"id": "d4a4b10e-5d22-4c23-8e09-f7a3e1c1a999",
"task_type": "create_vm",
"state": "FINISHED",
"error": null,
"created_on": "2026-05-23T05:07:31",
"finished_on": "2026-05-23T05:07:50",
"created_resources": {
"instances": ["169942e0-9b53-42df-95ef-1a8b6525c2bd"], // → resource ID
"volumes": ["726ecfcc-7fd0-4e30-a86e-7892524aa483"],
"floatingips": [],
"networks": [],
...
}
}
The resource ID is in the created_resources field under the resource type key. Only the types that were actually created contain non-empty arrays — all others are empty lists.
Polling intervals
Polling too frequently wastes API quota; polling too rarely delays pipelines. These intervals balance the two:
| Operation | Typical duration | Poll every |
|---|
| Create VM | 15–30 seconds | 5 seconds |
| Create volume | 5–15 seconds | 5 seconds |
| Create network / subnet | 5–10 seconds | 5 seconds |
| Create load balancer | 30–90 seconds | 10 seconds |
| Delete VM | 15–70 seconds | 5 seconds |
| Delete Bare Metal server | 60–120 seconds | 30 seconds |
| Create Kubernetes cluster | 5–15 minutes | 30 seconds |
Poll the task
curl (shell loop)
Python SDK
Go SDK
JavaScript
TASK_ID="{TASK_ID}"
while true; do
STATE=$(curl -s "https://api.gcore.com/cloud/v1/tasks/$TASK_ID" \
-H "Authorization: APIKey $GCORE_API_KEY" \
| grep -o '"state":"[^"]*"' | grep -o '[A-Z]*$' | tr -d '"')
echo "State: $STATE"
if [ "$STATE" = "FINISHED" ]; then break; fi
if [ "$STATE" = "ERROR" ]; then echo "Task failed"; exit 1; fi
sleep 5
done
import os, time
from gcore import Gcore
client = Gcore(api_key=os.environ["GCORE_API_KEY"])
# Built-in blocking poll — no manual loop needed
task = client.cloud.tasks.poll(
"{TASK_ID}",
polling_interval_seconds=5,
polling_timeout_seconds=300,
)
instance_id = task.created_resources.instances[0]
import "time"
taskID := "{TASK_ID}"
for {
task, err := client.Cloud.Tasks.Get(context.TODO(), taskID)
if err != nil { panic(err) }
if task.State == "FINISHED" {
instanceID := task.CreatedResources.Instances[0]
fmt.Println("Instance:", instanceID)
break
}
if task.State == "ERROR" {
panic("Task failed: " + *task.Error)
}
time.Sleep(5 * time.Second)
}
async function pollTask(taskId, intervalMs = 5000) {
const headers = { Authorization: `APIKey ${process.env.GCORE_API_KEY}` };
while (true) {
const res = await fetch(
`https://api.gcore.com/cloud/v1/tasks/${taskId}`,
{ headers }
);
const task = await res.json();
if (task.state === "FINISHED") return task.created_resources;
if (task.state === "ERROR") throw new Error(task.error);
await new Promise(r => setTimeout(r, intervalMs));
}
}
const resources = await pollTask("{TASK_ID}");
console.log("Instance:", resources.instances[0]);
Error tasks
When state is ERROR, the error field contains the failure reason:
{
"state": "ERROR",
"error": "Quota limit for volume_size exceeded by 20",
"created_resources": null
}
On error, no resources from that task are created — there is nothing to clean up from the failed task itself.
List recent tasks
To see all tasks in a project and region, call:
curl "https://api.gcore.com/cloud/v1/tasks?limit=20&state=RUNNING" \
-H "Authorization: APIKey $GCORE_API_KEY"
Filter by state (NEW, RUNNING, FINISHED, ERROR) and task_type (e.g., create_vm, delete_vm, create_volume).
Tasks are associated with a specific project and region, whereas the task endpoint GET /cloud/v1/tasks/{task_id} does not require project_id or region_id in the path — a task ID is globally unique.