curl --request POST \
--url https://api.checkfu.com/v1/skills \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'checkfu-version: <checkfu-version>' \
--data '
{
"name": "<string>",
"display_name": "<string>",
"description": "<string>",
"instructions": "<string>",
"files": [
{
"path": "<string>",
"content_base64": "<string>"
}
]
}
'import requests
url = "https://api.checkfu.com/v1/skills"
payload = {
"name": "<string>",
"display_name": "<string>",
"description": "<string>",
"instructions": "<string>",
"files": [
{
"path": "<string>",
"content_base64": "<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({
name: '<string>',
display_name: '<string>',
description: '<string>',
instructions: '<string>',
files: [{path: '<string>', content_base64: '<string>'}]
})
};
fetch('https://api.checkfu.com/v1/skills', 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/skills",
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([
'name' => '<string>',
'display_name' => '<string>',
'description' => '<string>',
'instructions' => '<string>',
'files' => [
[
'path' => '<string>',
'content_base64' => '<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/skills"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"display_name\": \"<string>\",\n \"description\": \"<string>\",\n \"instructions\": \"<string>\",\n \"files\": [\n {\n \"path\": \"<string>\",\n \"content_base64\": \"<string>\"\n }\n ]\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/skills")
.header("checkfu-version", "<checkfu-version>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"display_name\": \"<string>\",\n \"description\": \"<string>\",\n \"instructions\": \"<string>\",\n \"files\": [\n {\n \"path\": \"<string>\",\n \"content_base64\": \"<string>\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.checkfu.com/v1/skills")
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 \"name\": \"<string>\",\n \"display_name\": \"<string>\",\n \"description\": \"<string>\",\n \"instructions\": \"<string>\",\n \"files\": [\n {\n \"path\": \"<string>\",\n \"content_base64\": \"<string>\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"workspace_id": "<string>",
"name": "<string>",
"kind": "instructional",
"description": "<string>",
"instructions": "<string>",
"files": [
{
"path": "<string>",
"content_base64": "<string>",
"sha256": "<string>",
"bytes": 1
}
],
"version": 1,
"created_at": "<string>",
"updated_at": "<string>",
"display_name": "<string>",
"status": "active"
}{
"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.conflict",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#validation-conflict"
}
}{
"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"
}
}Create a Skill
Create a Workspace Skill from instructions plus up to 256 base64-encoded files. name is the unique logical identity; optional display_name is a non-unique presentation label and null or omission falls back to name. Each file path is a normalized relative POSIX path; paths must be unique, cannot equal or descend from the generated SKILL.md, and cannot be an ancestor of another file path. kind is either instructional (content the agent loads) or executable (content it runs); the two are never conflated. Every committed edit produces a new immutable version that Session admission can pin. You do not need to create the platform-curated document skills (pptx, xlsx, docx, pdf) — they are attachable by short name in every Workspace already; creating your own Skill under one of those names shadows the curated content for that Workspace. Accepts an Idempotency-Key.
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/skills \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'checkfu-version: <checkfu-version>' \
--data '
{
"name": "<string>",
"display_name": "<string>",
"description": "<string>",
"instructions": "<string>",
"files": [
{
"path": "<string>",
"content_base64": "<string>"
}
]
}
'import requests
url = "https://api.checkfu.com/v1/skills"
payload = {
"name": "<string>",
"display_name": "<string>",
"description": "<string>",
"instructions": "<string>",
"files": [
{
"path": "<string>",
"content_base64": "<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({
name: '<string>',
display_name: '<string>',
description: '<string>',
instructions: '<string>',
files: [{path: '<string>', content_base64: '<string>'}]
})
};
fetch('https://api.checkfu.com/v1/skills', 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/skills",
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([
'name' => '<string>',
'display_name' => '<string>',
'description' => '<string>',
'instructions' => '<string>',
'files' => [
[
'path' => '<string>',
'content_base64' => '<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/skills"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"display_name\": \"<string>\",\n \"description\": \"<string>\",\n \"instructions\": \"<string>\",\n \"files\": [\n {\n \"path\": \"<string>\",\n \"content_base64\": \"<string>\"\n }\n ]\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/skills")
.header("checkfu-version", "<checkfu-version>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"display_name\": \"<string>\",\n \"description\": \"<string>\",\n \"instructions\": \"<string>\",\n \"files\": [\n {\n \"path\": \"<string>\",\n \"content_base64\": \"<string>\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.checkfu.com/v1/skills")
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 \"name\": \"<string>\",\n \"display_name\": \"<string>\",\n \"description\": \"<string>\",\n \"instructions\": \"<string>\",\n \"files\": [\n {\n \"path\": \"<string>\",\n \"content_base64\": \"<string>\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"workspace_id": "<string>",
"name": "<string>",
"kind": "instructional",
"description": "<string>",
"instructions": "<string>",
"files": [
{
"path": "<string>",
"content_base64": "<string>",
"sha256": "<string>",
"bytes": 1
}
],
"version": 1,
"created_at": "<string>",
"updated_at": "<string>",
"display_name": "<string>",
"status": "active"
}{
"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.conflict",
"message": "<string>",
"more": "https://docs.checkfu.com/reference/errors#validation-conflict"
}
}{
"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 255Body
^[a-z0-9](?:[a-z0-9._-]{0,93})$instructional, executable An optional non-unique Skill presentation label; clients fall back to the logical name when absent or null.
1 - 255163841048576At most 256 files. Paths must be unique, may not be an ancestor of another path, and may not equal or descend from the generated SKILL.md entry.
256Show child attributes
Show child attributes
Response
Success
^skl_[0-9a-f]{32}$^wrkspc_[0-9a-f]{32}$^[a-z0-9](?:[a-z0-9._-]{0,93})$instructional, executable 16384Show child attributes
Show child attributes
x > 0An optional non-unique Skill presentation label; clients fall back to the logical name when absent or null.
1 - 255active, archived