Skip to main content
POST
/
skills
/
v1
/
import
Import a Skill
curl --request POST \
  --url https://api.langdock.com/skills/v1/import \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: multipart/form-data' \
  --form file='@example-file' \
  --form mode=create \
  --form 'integrationIds=<string>'
import requests

url = "https://api.langdock.com/skills/v1/import"

files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"mode": "create",
"integrationIds": "<string>"
}
headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, data=payload, files=files, headers=headers)

print(response.text)
const form = new FormData();
form.append('file', '<string>');
form.append('mode', 'create');
form.append('integrationIds', '<string>');

const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

options.body = form;

fetch('https://api.langdock.com/skills/v1/import', 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.langdock.com/skills/v1/import",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mode\"\r\n\r\ncreate\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"integrationIds\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);

$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.langdock.com/skills/v1/import"

payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mode\"\r\n\r\ncreate\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"integrationIds\"\r\n\r\n<string>\r\n-----011000010111000001101001--")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")

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.langdock.com/skills/v1/import")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mode\"\r\n\r\ncreate\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"integrationIds\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.langdock.com/skills/v1/import")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mode\"\r\n\r\ncreate\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"integrationIds\"\r\n\r\n<string>\r\n-----011000010111000001101001--"

response = http.request(request)
puts response.read_body
{
  "skill": {
    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "name": "<string>",
    "slug": "<string>",
    "description": "<string>",
    "instructions": "<string>",
    "integrationIds": [
      "3c90c3cc-0d44-4b50-8888-8dd25736052a"
    ],
    "createdAt": "2023-11-07T05:31:56Z",
    "updatedAt": "2023-11-07T05:31:56Z"
  },
  "files": [
    {
      "path": "<string>",
      "sizeBytes": 123,
      "extension": "<string>",
      "hasScript": true
    }
  ]
}
{
"skill": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"slug": "<string>",
"description": "<string>",
"instructions": "<string>",
"integrationIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
},
"files": [
{
"path": "<string>",
"sizeBytes": 123,
"extension": "<string>",
"hasScript": true
}
]
}
Using our API via a dedicated deployment? Just replace api.langdock.com with your deployment’s base URL: <deployment-url>/api/public
Imports a Skill from a SKILL.md file or a zip archive. Use this endpoint to sync repository-managed Skills into Langdock.

Required Scopes

This endpoint requires the SKILL_API scope.
Creating a new Skill requires the createSkills workspace permission. Updating an existing Skill with mode: "upsert" requires editor access to the matching Skill.

Request Format

Send the request as multipart/form-data.
FieldTypeRequiredDescription
filefileYesSKILL.md, .zip, or .skill file content.
fileTypestringYesFile parser to use: md or zip. Use zip for .zip and .skill archives.
modestringNoImport mode: create or upsert. Default: create.
integrationIdsstringNoJSON-encoded array of integration UUIDs to attach, for example ["550e8400-e29b-41d4-a716-446655440000"].

SKILL.md Format

The imported Skill must include YAML frontmatter followed by instructions:
SKILL.md
---
name: Support Reply Style
slug: support-reply-style
description: Applies the support team's tone and escalation rules.
---

Write concise replies, include the next best action, and escalate billing issues to the account owner.
Frontmatter FieldRequiredDescription
nameYesSkill name. Maximum: 64 characters.
slugNoStable Skill slug. If omitted, Langdock generates one from the name.
descriptionNoDescription used to explain when the Skill should apply. Maximum: 1024 characters.
licenseNoOptional license metadata.

Zip archive rules

Zip archives must contain a SKILL.md file at the root or inside one top-level directory. Langdock stores allowed supporting files with the Skill and skips unsupported file types.
LimitValue
Upload size25 MB
Total uncompressed size20 MB
Individual file size5 MB
Files per archive200
Supported supporting file types include Markdown, text, Python, shell, JavaScript, TypeScript, JSON, YAML, TOML, CSV, XML, HTML, CSS, SVG, PDF, Office files, fonts, and common image formats.

Import Modes

ModeBehavior
createCreates a new Skill from the import. The request fails if the slug already exists.
upsertUpdates one editable Skill with the same slug, or creates a new Skill if none exists. The request fails if multiple editable Skills use the same slug.
When an upsert updates an existing Skill, imported files replace the Skill’s existing stored files.

Example

const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");

async function importSkill() {
  const form = new FormData();
  form.append("file", fs.createReadStream("./support-reply-style.zip"));
  form.append("fileType", "zip");
  form.append("mode", "upsert");
  form.append("integrationIds", JSON.stringify([]));

  const response = await axios.post(
    "https://api.langdock.com/skills/v1/import",
    form,
    {
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        ...form.getHeaders()
      }
    }
  );

  console.log("Imported Skill:", response.data.skill.id);
}

importSkill();

Response Format

Success Response (200 OK or 201 Created)

{
  skill: {
    id: string;
    name: string;
    slug: string;
    description: string;
    instructions: string;
    integrationIds: string[];
    createdAt: string;
    updatedAt: string;
  };
  files: Array<{
    path: string;
    sizeBytes: number;
    extension: string;
    hasScript: boolean;
  }>;
}
200 OK means an existing Skill was updated through upsert. 201 Created means a new Skill was created.

Error Handling

Status CodeDescription
400Invalid form data, invalid SKILL.md, invalid zip archive, or inaccessible integrationIds
401Invalid or missing API key
403Missing SKILL_API scope, Skills product access, create permission, or editor access
409Existing slug conflict or ambiguous upsert slug
413Uploaded file is too large
429Rate limit exceeded
500Internal server error
Langdock intentionally blocks browser-origin requests to protect your API key and ensure your applications remain secure. For more information, please see our guide on API Key Best Practices.

Authorizations

Authorization
string
header
required

API key as Bearer token. Format "Bearer YOUR_API_KEY"

Body

multipart/form-data
file
file
required

SKILL.md, .zip, or .skill file content.

fileType
enum<string>
required

File parser to use.

Available options:
md,
zip
mode
enum<string>
default:create

Whether to create a Skill or update an editable Skill with the same slug.

Available options:
create,
upsert
integrationIds
string

JSON-encoded array of integration UUIDs.

Response

Existing Skill updated successfully

skill
object
required
files
object[]
required