curl --request POST \
--url https://api.checkfu.com/v1/skill-proposals/{id}/submit \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'checkfu-version: <checkfu-version>' \
--data '
{
"expected_version": 1,
"skill_source": "<string>",
"acted_as": "<string>"
}
'import requests
url = "https://api.checkfu.com/v1/skill-proposals/{id}/submit"
payload = {
"expected_version": 1,
"skill_source": "<string>",
"acted_as": "<string>"
}
headers = {
"checkfu-version": "<checkfu-version>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'checkfu-version': '<checkfu-version>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({expected_version: 1, skill_source: '<string>', acted_as: '<string>'})
};
fetch('https://api.checkfu.com/v1/skill-proposals/{id}/submit', 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.checkfu.com/v1/skill-proposals/{id}/submit",
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([
'expected_version' => 1,
'skill_source' => '<string>',
'acted_as' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"checkfu-version: <checkfu-version>"
],
]);
$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.checkfu.com/v1/skill-proposals/{id}/submit"
payload := strings.NewReader("{\n \"expected_version\": 1,\n \"skill_source\": \"<string>\",\n \"acted_as\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("checkfu-version", "<checkfu-version>")
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.checkfu.com/v1/skill-proposals/{id}/submit")
.header("checkfu-version", "<checkfu-version>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expected_version\": 1,\n \"skill_source\": \"<string>\",\n \"acted_as\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.checkfu.com/v1/skill-proposals/{id}/submit")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["checkfu-version"] = '<checkfu-version>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expected_version\": 1,\n \"skill_source\": \"<string>\",\n \"acted_as\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "authoring",
"source_session_ids": [
"<string>"
],
"agent": "<string>",
"model_routing_profile_key": "<string>",
"instructions": "<string>",
"skill": {
"name": "<string>",
"description": "<string>",
"kind": "instructional",
"entry": "<string>",
"content_sha256": "<string>"
},
"verification_material": {
"task": "<string>",
"rubric": "<string>"
},
"verifications": [
{
"session": "<string>",
"started_at": "<string>",
"result": {
"verdict": "satisfied",
"explanation": "<string>",
"cost_tokens": 1,
"completed_at": "<string>"
},
"source_version": 1,
"principal": "<string>",
"launched_at": "<string>"
}
],
"submission": {
"skill_source": "<string>",
"branch": "<string>",
"commit_sha": "<string>",
"submitted_at": "<string>"
},
"adoption": {
"skill_id": "<string>",
"skill_version": 1,
"observed_at": "<string>"
},
"error": "input_session_unavailable",
"usage": {
"input_tokens": 1,
"cached_input_tokens": 1,
"cache_write_input_tokens": 1,
"output_tokens": 1,
"reasoning_output_tokens": 1,
"total_tokens": 1
},
"created_at": "<string>",
"updated_at": "<string>",
"version": 1,
"submission_attempt": {
"source_version": 1,
"skill_source": "<string>",
"acted_as": "<string>",
"branch": "<string>",
"base_commit_sha": "<string>",
"base_content_sha256": "<string>",
"expected_base_digest": "<string>",
"prepared_commit_sha": "<string>",
"started_at": "<string>"
}
}{
"error": {
"type": "validation.malformed",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#validation-malformed"
}
}{
"error": {
"type": "auth.invalid_key",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#auth-invalid-key"
}
}{
"error": {
"type": "auth.disabled_tenancy",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#auth-disabled-tenancy"
}
}{
"error": {
"type": "validation.not_found",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#validation-not-found"
}
}{
"error": {
"type": "runtime.invalid_transition",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#runtime-invalid-transition"
}
}{
"error": {
"type": "budget.exceeded",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#budget-exceeded"
}
}{
"error": {
"type": "runtime.internal",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#runtime-internal"
}
}Submit a Skill proposal to its SkillSource
Open a change-proposal branch in the bound SkillSource’s repository through its governed Connection. Only a verified proposal may begin submission; expected_version must equal that reviewed proposal version, and acted_as must own and hold use_connection on the source Project’s Connection. The row first enters durable submitting with the exact original authority. After a timeout, resend the original payload (and the same Idempotency-Key when supplied): preparation, branch-head comparison, and ambiguous CAS readback recover one exact commit and branch. submitted is terminal; the human merge and ordinary sync remain the only path to a live Skill.
Checkfu support posture: alpha; hosted. Required evidence journey: skill-delivery. Deployment-specific readiness and the latest proven release are available from GET /v1/support/capabilities.
curl --request POST \
--url https://api.checkfu.com/v1/skill-proposals/{id}/submit \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'checkfu-version: <checkfu-version>' \
--data '
{
"expected_version": 1,
"skill_source": "<string>",
"acted_as": "<string>"
}
'import requests
url = "https://api.checkfu.com/v1/skill-proposals/{id}/submit"
payload = {
"expected_version": 1,
"skill_source": "<string>",
"acted_as": "<string>"
}
headers = {
"checkfu-version": "<checkfu-version>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'checkfu-version': '<checkfu-version>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({expected_version: 1, skill_source: '<string>', acted_as: '<string>'})
};
fetch('https://api.checkfu.com/v1/skill-proposals/{id}/submit', 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.checkfu.com/v1/skill-proposals/{id}/submit",
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([
'expected_version' => 1,
'skill_source' => '<string>',
'acted_as' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"checkfu-version: <checkfu-version>"
],
]);
$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.checkfu.com/v1/skill-proposals/{id}/submit"
payload := strings.NewReader("{\n \"expected_version\": 1,\n \"skill_source\": \"<string>\",\n \"acted_as\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("checkfu-version", "<checkfu-version>")
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.checkfu.com/v1/skill-proposals/{id}/submit")
.header("checkfu-version", "<checkfu-version>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expected_version\": 1,\n \"skill_source\": \"<string>\",\n \"acted_as\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.checkfu.com/v1/skill-proposals/{id}/submit")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["checkfu-version"] = '<checkfu-version>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expected_version\": 1,\n \"skill_source\": \"<string>\",\n \"acted_as\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "authoring",
"source_session_ids": [
"<string>"
],
"agent": "<string>",
"model_routing_profile_key": "<string>",
"instructions": "<string>",
"skill": {
"name": "<string>",
"description": "<string>",
"kind": "instructional",
"entry": "<string>",
"content_sha256": "<string>"
},
"verification_material": {
"task": "<string>",
"rubric": "<string>"
},
"verifications": [
{
"session": "<string>",
"started_at": "<string>",
"result": {
"verdict": "satisfied",
"explanation": "<string>",
"cost_tokens": 1,
"completed_at": "<string>"
},
"source_version": 1,
"principal": "<string>",
"launched_at": "<string>"
}
],
"submission": {
"skill_source": "<string>",
"branch": "<string>",
"commit_sha": "<string>",
"submitted_at": "<string>"
},
"adoption": {
"skill_id": "<string>",
"skill_version": 1,
"observed_at": "<string>"
},
"error": "input_session_unavailable",
"usage": {
"input_tokens": 1,
"cached_input_tokens": 1,
"cache_write_input_tokens": 1,
"output_tokens": 1,
"reasoning_output_tokens": 1,
"total_tokens": 1
},
"created_at": "<string>",
"updated_at": "<string>",
"version": 1,
"submission_attempt": {
"source_version": 1,
"skill_source": "<string>",
"acted_as": "<string>",
"branch": "<string>",
"base_commit_sha": "<string>",
"base_content_sha256": "<string>",
"expected_base_digest": "<string>",
"prepared_commit_sha": "<string>",
"started_at": "<string>"
}
}{
"error": {
"type": "validation.malformed",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#validation-malformed"
}
}{
"error": {
"type": "auth.invalid_key",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#auth-invalid-key"
}
}{
"error": {
"type": "auth.disabled_tenancy",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#auth-disabled-tenancy"
}
}{
"error": {
"type": "validation.not_found",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#validation-not-found"
}
}{
"error": {
"type": "runtime.invalid_transition",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#runtime-invalid-transition"
}
}{
"error": {
"type": "budget.exceeded",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#budget-exceeded"
}
}{
"error": {
"type": "runtime.internal",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#runtime-internal"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
2026-08-27 255Path Parameters
^skp_[0-9a-f]{32}$Body
Response
an error exactly on authoring failure, an artifact exactly past authoring, a pending submission while submitting and optionally retained after submission for recovery, a completed submission exactly on submitted, adoption only after submission, and verification states only with a recorded attempt
^skp_[0-9a-f]{32}$authoring, drafted, authoring_failed, verifying, verified, verification_failed, submitting, submitted, discarded 1 - 8 elements^sess_[0-9a-f]{32}$^agent_[0-9a-f]{32}$^[a-z0-9](?:[a-z0-9._-]{0,93})$4096Show child attributes
Show child attributes
Show child attributes
Show child attributes
8Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
input_session_unavailable, input_sessions_too_large, authoring_failed, internal Show child attributes
Show child attributes
x > 0Show child attributes
Show child attributes