Import Skill
Create or update a Skill from a SKILL.md file or zip archive
Imports a Skill from a SKILL.md file or a zip archive. Use this endpoint to sync repository-managed Skills into ajan.
Base URL
https://api.ajan.io/skills/v1/importRequired Scopes
This endpoint requires the SKILL_API scope.
Request Format
Send the request as multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | SKILL.md, .zip, or .skill file content. |
fileType | string | Yes | File parser to use: md or zip. Use zip for .zip and .skill archives. |
mode | string | No | Import mode: create or upsert. Default: create. |
integrationIds | string | No | JSON-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:
---
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 Field | Required | Description |
|---|---|---|
name | Yes | Skill name. Maximum: 64 characters. |
slug | No | Stable Skill slug. If omitted, ajan generates one from the name. |
description | No | Description used to explain when the Skill should apply. Maximum: 1024 characters. |
license | No | Optional license metadata. |
Zip archive rules
Zip archives must contain a SKILL.md file at the root or inside one top-level directory. ajan stores allowed supporting files with the Skill and skips unsupported file types.
| Limit | Value |
|---|---|
| Upload size | 25 MB |
| Total uncompressed size | 20 MB |
| Individual file size | 5 MB |
| Files per archive | 200 |
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
| Mode | Behavior |
|---|---|
create | Creates a new Skill from the import. The request fails if the slug already exists. |
upsert | Updates 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.ajan.io/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 Code | Description |
|---|---|
| 400 | Invalid form data, invalid SKILL.md, invalid zip archive, or inaccessible integrationIds |
| 401 | Invalid or missing API key |
| 403 | Missing SKILL_API scope, Skills product access, create permission, or editor access |
| 409 | Existing slug conflict or ambiguous upsert slug |
| 413 | Uploaded file is too large |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
OpenAPI
openapi: 3.0.0
info:
title: ajan API
version: 3.0.0
servers:
- url: https://api.ajan.io
description: Production
security:
- bearerAuth: []
paths:
/skills/v1/import:
post:
tags:
- Skills
summary: Import a Skill
description: Creates or updates a Skill from a SKILL.md file or zip archive.
operationId: importSkill
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/ImportSkillRequest'
responses:
'200':
description: Existing Skill updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ImportSkillResponse'
'201':
description: Skill created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ImportSkillResponse'
'400':
description: Invalid form data or zip archive
'401':
description: Invalid or missing API key
'403':
description: Missing required scope or Skill permission
'409':
description: Existing slug conflict or ambiguous upsert slug
'413':
description: Uploaded file is too large
'429':
description: Rate limit exceeded
'500':
description: Internal server error
components:
schemas:
ImportSkillRequest:
type: object
required:
- file
- fileType
properties:
file:
type: string
format: binary
description: SKILL.md, .zip, or .skill file content.
fileType:
type: string
enum:
- md
- zip
description: File parser to use.
mode:
type: string
enum:
- create
- upsert
default: create
description: >-
Whether to create a Skill or update an editable Skill with the same
slug.
integrationIds:
type: string
description: JSON-encoded array of integration UUIDs.
ImportSkillResponse:
type: object
required:
- skill
- files
properties:
skill:
$ref: '#/components/schemas/Skill'
files:
type: array
items:
$ref: '#/components/schemas/ImportedSkillFile'
Skill:
type: object
required:
- id
- name
- slug
- description
- instructions
- integrationIds
- createdAt
- updatedAt
properties:
id:
type: string
format: uuid
description: Unique identifier for the Skill.
name:
type: string
maxLength: 64
description: Skill name.
slug:
type: string
maxLength: 100
pattern: ^[a-z0-9-]+$
description: Stable Skill slug.
description:
type: string
maxLength: 1024
description: Description used to explain when the Skill should apply.
instructions:
type: string
maxLength: 50000
description: Skill instructions.
integrationIds:
type: array
items:
type: string
format: uuid
description: >-
Integration IDs attached to the Skill. Each integration must be
enabled in your workspace.
createdAt:
type: string
format: date-time
description: ISO 8601 timestamp for Skill creation.
updatedAt:
type: string
format: date-time
description: ISO 8601 timestamp for the latest Skill update.
ImportedSkillFile:
type: object
required:
- path
- sizeBytes
- extension
- hasScript
properties:
path:
type: string
description: File path inside the imported Skill.
sizeBytes:
type: integer
description: File size in bytes.
extension:
type: string
description: File extension.
hasScript:
type: boolean
description: Whether the file is a script file.
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: API Key
description: API key as Bearer token. Format "Bearer YOUR_API_KEY"