curl --request POST \
--url https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"job_id": "<string>",
"lease_id": "<string>"
}
'import requests
url = "https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment"
payload = {
"job_id": "<string>",
"lease_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({job_id: '<string>', lease_id: '<string>'})
};
fetch('https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'job_id' => '<string>',
'lease_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment"
payload := strings.NewReader("{\n \"job_id\": \"<string>\",\n \"lease_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"job_id\": \"<string>\",\n \"lease_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"job_id\": \"<string>\",\n \"lease_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"message": "<string>",
"stack_id": "<string>",
"job_id": "<string>",
"source_job_id": "<string>",
"lease_id": "<string>",
"server_id": "<string>",
"idempotent_replay": true,
"provider_vm_create_requested": false,
"bootstrap_token": "<string>",
"bootstrap_token_expires_at": "2023-11-07T05:31:56Z",
"owner_spec_endpoint": "<string>",
"owner_spec_scopes": [
"<string>"
]
},
"meta": {
"total": 123,
"page": 123,
"per_page": 123,
"managed_runtime_inventory_complete": true,
"worker_inventory_sha256": "<string>",
"managed_runtime_active_lease_ids": [
"<string>"
],
"managed_runtime_inactive_lease_ids": [
"<string>"
],
"managed_runtime_lease_generation_digests": [
{
"lease_id": "<string>",
"resource_generation_digest": "<string>"
}
],
"managed_runtime_duplicate_lease_ids": [
"<string>"
],
"managed_runtime_attachment_conflict_lease_ids": [
"<string>"
]
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}Resume one overdue managed Node wait on its exact existing VM
Authenticated, idempotent recovery for a persisted waiting_enrollment,
waiting_provider_provision, or waiting_canonical_guard job whose
next_resume_at has been overdue beyond the bounded grace period. The
server validates the owned StackKit deployment, source job, wait reason,
exact lease, active foundation role, and canonical Node as one operation. It
atomically retires the exact source wait, creates or rehydrates one
deterministic replacement deploy bound to the same lease and Node,
and replays that job on later calls. Before handler entry,
queue workers atomically acquire the durable tenant/stack compatibility
execution claim; this serializes different jobs for the same StackKit
deployment across Techstack
replicas. The claim remains durable running until the handler exits,
including during cancellation. This endpoint never invokes provider VM
creation or selects a newer VM. A replacement found durable running
after a crash remains fail-closed, is reported as the same job, and is
never duplicated automatically; runtime-action reconciliation remains a
separate operator concern.
curl --request POST \
--url https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"job_id": "<string>",
"lease_id": "<string>"
}
'import requests
url = "https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment"
payload = {
"job_id": "<string>",
"lease_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({job_id: '<string>', lease_id: '<string>'})
};
fetch('https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'job_id' => '<string>',
'lease_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment"
payload := strings.NewReader("{\n \"job_id\": \"<string>\",\n \"lease_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"job_id\": \"<string>\",\n \"lease_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kombify.io/v1/techstack/api/v1/stacks/{id}/resume-enrollment")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"job_id\": \"<string>\",\n \"lease_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"message": "<string>",
"stack_id": "<string>",
"job_id": "<string>",
"source_job_id": "<string>",
"lease_id": "<string>",
"server_id": "<string>",
"idempotent_replay": true,
"provider_vm_create_requested": false,
"bootstrap_token": "<string>",
"bootstrap_token_expires_at": "2023-11-07T05:31:56Z",
"owner_spec_endpoint": "<string>",
"owner_spec_scopes": [
"<string>"
]
},
"meta": {
"total": 123,
"page": 123,
"per_page": 123,
"managed_runtime_inventory_complete": true,
"worker_inventory_sha256": "<string>",
"managed_runtime_active_lease_ids": [
"<string>"
],
"managed_runtime_inactive_lease_ids": [
"<string>"
],
"managed_runtime_lease_generation_digests": [
{
"lease_id": "<string>",
"resource_generation_digest": "<string>"
}
],
"managed_runtime_duplicate_lease_ids": [
"<string>"
],
"managed_runtime_attachment_conflict_lease_ids": [
"<string>"
]
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "<string>",
"details": "<unknown>"
}
}Autorisierungen
OIDC/JWKS bearer token. Self-hosted defaults to Pocket ID; SaaS uses Auth0 through the edge. PocketBase JWT is legacy migration compatibility only.
Pfadparameter
Stack ID
