Documentation
Everything you need to save, share, verify, and install skills.
Overview
SkillSafe is the verified registry for AI agent skills. Unlike open registries where anyone can upload unscanned code, SkillSafe scans every skill before sharing and independently re-verifies on install. Cryptographic tree hashes ensure that what the publisher uploaded is byte-for-byte identical to what you receive.
For AI tool integration, your agent can read the machine-readable skill definition at /skill.md.
What are Skills?
Skills are reusable instruction sets that teach AI agents (like Claude Code, Cursor, Windsurf, Codex, Gemini, OpenCode, OpenClaw, Cline, Roo, Goose, Copilot, Kiro, Trae, AMP, Aider, VS Code, Antigravity, Droid, and Kilo Code) new capabilities — from code review to deployment automation. Each skill is a directory containing a SKILL.md definition file and any supporting scripts. SkillSafe provides a verified registry where you can save, share, and install skills with security scanning and cryptographic verification.
Quick Start
1. Install SkillSafe
Send this to your AI agent:
Create skillsafe skill from https://skillsafe.ai/skill.md Your AI agent reads the skill definition and sets up SkillSafe automatically. All operations use the REST API — no CLI installation needed.
2. Scan a Skill
curl -X POST https://api.skillsafe.ai/v1/scan/github \
-H "Content-Type: application/json" \
-d '{"url":"https://github.com/owner/repo"}' Scan any GitHub-hosted skill for security issues. No installation required — just curl. Analyzes Python, JavaScript, TypeScript, and Markdown files for malicious patterns, credential theft, and prompt injection.
3. Search & Browse
curl "https://api.skillsafe.ai/v1/skills/search?q=code-review&sort=popular" Search the registry for skills. All read operations (search, info, scan) require no authentication.
4. Install
curl "https://api.skillsafe.ai/v1/skills/@skillsafe/code-review/download/1.0.0" No registration required for public skills. Returns a file manifest — download each blob via the API. New to SkillSafe? Tell your AI agent: install @skillsafe/code-review from skillsafe.ai
Authentication
Sign-In Methods
SkillSafe supports multiple sign-in methods:
- Google Sign-In — One-click OAuth via Google account
- GitHub Sign-In — OAuth via GitHub account
- Email & Password — Sign in with email verification
- API Device Flow —
POST /v1/auth/clicreates a session, user approves in browser, agent polls for API key
API Keys (CLI)
CLI and programmatic requests use a Bearer token:
Authorization: Bearer sk_your_api_key_here API keys are hashed with SHA-256 before storage. The server never stores plaintext keys. Browser sessions use HttpOnly cookies instead of Bearer tokens.
⚠️ Never commit API keys to source control. Use environment variables instead.
🔒 Never share your API keys. Keep them secret and rotate them immediately if compromised.
Key Limits
- All tiers: max 20 active keys per account
Manage keys at /account/keys.
Saving & Sharing
Saving a Skill
Skills are saved privately by default. No email verification or scan report required.
POST /v1/skills/@{namespace}/{name}
Content-Type: multipart/form-data
Fields:
metadata — JSON with version, description, category, tags, changelog, github_repo_url, file_manifest
scan_report — JSON scan report (optional for save)
file_* — individual skill files (one per form field, filename carries relative path) Creating a Share Link
Sharing creates a link others can use to download and verify a saved version. Requires email verification and a scan report.
POST /v1/skills/@{namespace}/{name}/versions/{version}/share
Body (JSON):
visibility — "private" (link-only) or "public" (discoverable via search)
expires_in — "1d", "7d", "30d", or "never"
allow_reshare — boolean (optional) — whether the recipient may reshare Metadata Field Limits
description: max 2,000 characterscategory: max 100 characterstags: max 1,000 characterschangelog: max 5,000 characters
Size Limits
- Max upload: 15 MB per version (v2 format: 10 MB total file content)
- Free: 50 MB total account storage | Paid: 5 GB | Enterprise: 10 GB
Daily Publish Limits
Version saves are rate-limited per account on a rolling 24-hour window:
- Free: 50 versions / 24h
- Paid: 200 versions / 24h
- Enterprise: 1,000 versions / 24h
Agent Limits
- Free: 1 agent, 5 snapshots per agent, 1 MB per snapshot
- Paid: 5 agents, 50 snapshots per agent, 10 MB per snapshot
- Enterprise: unlimited agents & snapshots, 50 MB per snapshot
Installing a Skill
No account required to install public skills. Tell your AI agent: install @namespace/name from skillsafe.ai. Or use the API directly:
# Get file manifest
curl "https://api.skillsafe.ai/v1/skills/@ns/name/download/1.0.0"
# Download individual files
curl "https://api.skillsafe.ai/v1/blobs/sha256:abc..." Public skills require no authentication. Private skills require a Bearer token in the Authorization header.
Verification Model
SkillSafe uses dual-side verification.
Reports match. Safe to install.
Reports disagree. Review before installing.
Tree hashes mismatch. Do not install.
Searching
API
curl "https://api.skillsafe.ai/v1/skills/search?q=formatter&sort=popular"
curl "https://api.skillsafe.ai/v1/skills/@skillsafe/code-review" Use search to find public skills by keyword, category, or sort order. Use info to view details about a specific skill. Use list to show all locally installed skills across Claude Code, Cursor, Windsurf, Codex, Gemini, OpenCode, OpenClaw, Cline, Roo, Goose, Copilot, Kiro, Trae, AMP, Aider, VS Code, Antigravity, ClawdBot, Droid, Kilo Code, and all other supported tool directories.
API
GET /v1/skills/search?q=formatter&sort=popular&limit=20 Sort: popular, recent, verified, trending, hot, stars, newest, installs, eval_score, relevance, updated
Additional filter parameters: category, namespace, tag, scan_clean (boolean — only skills with clean scan reports), eval_tested (boolean — only skills with eval results), type (skill or skillset), owner_type (filter by owner type).
CLI Utilities
The SkillSafe CLI is a single-file Python script (stdlib only, no pip dependencies). It is open source on GitHub — you can audit the scanner rules, verification logic, and every HTTP call it makes.
whoami — Check authentication status
skillsafe whoami Displays your local configuration (username, namespace, masked API key, config file path) and verifies your credentials against the server. Useful for confirming you are signed in and your API key is valid.
list — List installed skills
skillsafe list Shows all skills installed locally across all 20 supported tool directories (Claude Code, Cursor, Windsurf, Codex, Gemini, OpenCode, OpenClaw, Cline, Roo, Goose, Copilot, Kiro, Trae, AMP, Aider, VS Code, Antigravity, ClawdBot, Droid, Kilo Code). Each entry includes the skill name, version, and installation path.
yank — Mark a version unsafe
skillsafe yank @myname/my-skill --version 1.0.0 Marks a specific version as unsafe and hides it from future downloads. Yanked versions are blocked for new installs but do not affect skills already installed. Use this if you discover a security issue in a version you published. Requires authentication and must be the skill owner.
import — Import a skill from a URL
skillsafe import github.com/owner/repo
skillsafe import https://clawhub.ai/owner/skill Import a skill from a GitHub repository or ClawHub URL into the registry as a public placeholder. Requires authentication and email verification.
lint — Validate a manifest
skillsafe lint
skillsafe lint ./my-skill Validates a skillsafe.yaml manifest against the schema. Reports errors and warnings before you attempt to save or share.
demo — Upload a demo recording
skillsafe demo recording.json @myname/my-skill --version 1.0.0
skillsafe demo recording.json @myname/my-skill --version 1.0.0 --title "My demo" Upload a demo JSON recording (skillsafe-demo/1 schema) for a skill version. Demos are shown on the skill page. Requires authentication.
eval — Upload eval results
skillsafe eval @myname/my-skill --version 1.0.0 --eval-json results.json
skillsafe eval @myname/my-skill --version 1.0.0 --pass-rate 92.5 --test-cases 40 --pass-count 37 Upload automated eval results for a skill version. Accepts a skill-creator eval JSON file or raw pass-rate metrics. Results appear on the skill page and power the /v1/badge/:ns/:name/eval badge.
benchmark — Upload benchmark results
skillsafe benchmark @myname/my-skill --version 1.0.0 --runs 5 Upload benchmark performance results for a skill version. Use alongside eval for comprehensive quality data.
update — Upgrade a skill or the CLI
skillsafe update @skillsafe/code-review # upgrade one skill
skillsafe update --all # upgrade all installed skills
skillsafe update skillsafe # upgrade the CLI itself
skillsafe self-update # alias for: update skillsafe Upgrades an installed skill to the latest version, upgrades all skills with --all, or updates the CLI itself. Add --dry-run to preview changes without applying them. self-update is a shorthand alias for update skillsafe.
bom — Bill of Materials
skillsafe bom ./my-skill Generate a capability inventory for a local skill directory. Lists all files, detected capabilities (network, shell, filesystem, etc.), and the overall risk surface. Useful for auditing what a skill can do before saving or sharing.
demo-from-session — Convert a session to a demo
skillsafe demo-from-session session.jsonl @myname/my-skill --version 1.0.0 --title "My demo" Convert a Claude Code session JSONL file into a SkillSafe demo recording and upload it. Automatically extracts conversation turns into the skillsafe-demo/1 schema format.
claim — Claim a skill from another registry
skillsafe claim github.com/owner/repo Claim ownership of a skill imported from GitHub or another registry. Verifies you control the source repository. Requires authentication and email verification.
API Reference
Base URL: https://api.skillsafe.ai. All public endpoints are listed below. Admin-only endpoints are excluded.
| Method | Path | Auth | Description |
|---|---|---|---|
| Account | |||
| GET | /v1/account | Yes | Own profile, tier, and storage stats |
| PATCH | /v1/account | Yes | Update own profile (display name only) |
| POST | /v1/account/verify-email | Yes | Send email verification link |
| POST | /v1/account/claim | No | Verify email via claim token |
| GET | /v1/account/usage | Yes | Storage and API usage statistics |
| GET | /v1/account/skills | Yes | All own skills (private + public) |
| GET | /v1/account/keys | Yes | List active API keys |
| POST | /v1/account/keys | Yes | Generate a new API key |
| DELETE | /v1/account/keys/{id} | Yes | Revoke an API key |
| DELETE | /v1/account/keys | Yes | Revoke all API keys (emergency panic button) |
| DELETE | /v1/account/data | Yes | Purge all skills and data (keep account) |
| DELETE | /v1/account | Yes (verified) | Schedule account deletion (24 h grace period) |
| GET | /v1/users/{username} | No | Public profile for a user (skills, bio) |
| Auth | |||
| POST | /v1/auth/google | No | Google Sign-In; sets HttpOnly session cookie |
| POST | /v1/auth/github | No | GitHub OAuth; sets HttpOnly session cookie |
| POST | /v1/auth/logout | No | Log out and clear session cookie |
| POST | /v1/auth/key-exchange | Yes | Exchange Bearer token for HttpOnly session cookie |
| POST | /v1/auth/cli | No | Create CLI auth session (device flow) |
| GET | /v1/auth/cli/{id} | No | Poll session status; returns API key when approved |
| POST | /v1/auth/cli/{id}/approve | Yes | Approve CLI session from browser |
| POST | /v1/auth/email/send-code | No | Send 6-digit sign-in code to email |
| POST | /v1/auth/email/verify-code | No | Verify code and create session |
| POST | /v1/auth/email/login | No | Sign in with email and password |
| POST | /v1/auth/email/set-password | Yes | Set or change account password |
| POST | /v1/auth/email/register/send-code | No | Send registration verification code |
| POST | /v1/auth/email/register/verify | No | Verify code and create account with password |
| POST | /v1/auth/email/forgot-password | No | Send password-reset code to email |
| POST | /v1/auth/email/reset-password | No | Verify reset code and set new password |
| Skills | |||
| POST | /v1/skills/batch/versions | Optional | Check latest versions for multiple installed skills at once |
| POST | /v1/skills/@{ns}/{name} | Yes | Save a new skill version (multipart: archive + metadata) |
| GET | /v1/skills/@{ns}/{name} | Optional | Skill metadata, latest version, star count |
| DELETE | /v1/skills/@{ns}/{name} | Yes | Delete a skill |
| GET | /v1/skills/@{ns}/{name}/versions | Optional | List all versions (paginated) |
| GET | /v1/skills/@{ns}/{name}/versions/{version} | Optional | Version details including tree hash and scan report |
| GET | /v1/skills/@{ns}/{name}/download/{version} | Optional | Download skill file manifest |
| POST | /v1/skills/@{ns}/{name}/negotiate | Yes | Delta upload: determine which files need uploading (v2) |
| POST | /v1/skills/@{ns}/{name}/current-version | Yes | Pin the displayed current version |
| POST | /v1/skills/@{ns}/{name}/versions/{version}/yank | Yes (verified) | Yank a version (marks it unsafe, hides from downloads) |
| POST | /v1/skills/@{ns}/{name}/star | Yes | Star a skill |
| DELETE | /v1/skills/@{ns}/{name}/star | Yes | Unstar a skill |
| GET | /v1/skills/@{ns}/{name}/related | Optional | Other skills from the same GitHub repository |
| GET | /v1/skills/@{ns}/{name}/children | Optional | Child skills in a skillset (paginated) |
| GET | /v1/skills/@{ns}/{name}/readme | Optional | Cached GitHub README in markdown |
| GET | /v1/skills/@{ns}/{name}/versions/{version}/bom | Optional | Bill of Materials: capability inventory for a version |
| GET | /v1/blobs/{hash} | Optional | Download blob by SHA-256 hash (content-addressable, immutable) |
| GET | /v1/skills/search | No | Full-text search; sort by popular/recent/verified/trending/hot/stars/installs/eval_score/relevance/updated/newest |
| POST | /v1/skills/import-github | Yes (verified) | Import a GitHub repo as a public placeholder skill |
| POST | /v1/skills/import-github/batch | Yes (verified) | Batch import multiple sub-skills from a monorepo |
| POST | /v1/skills/discover-github | Yes (verified) | Discover SKILL.md files in a GitHub repository |
| POST | /v1/skills/import-url | Yes (verified) | Import a skill from any URL (GitHub or ClawHub) |
| Sharing | |||
| POST | /v1/skills/@{ns}/{name}/versions/{version}/share | Yes (verified) | Create share link (requires email verification + scan report) |
| GET | /v1/skills/@{ns}/{name}/versions/{version}/shares | Yes | List share links for a version |
| GET | /v1/share/{shareId} | No | Share link metadata (skill, version, expiry, access count) |
| GET | /v1/share/{shareId}/download | Optional | Download via share link (increments access counter) |
| DELETE | /v1/share/{shareId} | Yes | Revoke a share link |
| Verification | |||
| POST | /v1/skills/@{ns}/{name}/versions/{version}/verify | Yes | Submit consumer scan report; returns verdict (verified/divergent/critical) |
| Organizations | |||
| POST | /v1/orgs | Yes (verified) | Create organization (requires email verification) |
| GET | /v1/orgs | Yes | List organizations you belong to |
| GET | /v1/orgs/{orgId} | Yes | Organization details (members only) |
| PATCH | /v1/orgs/{orgId} | Yes | Update org display name (owner only) |
| PATCH | /v1/orgs/{orgId}/name | Yes | Rename org namespace (owner only) |
| DELETE | /v1/orgs/{orgId} | Yes | Delete organization (owner only) |
| GET | /v1/orgs/{orgId}/skills | Yes | List org skills (members only) |
| GET | /v1/orgs/{orgId}/members | Yes | List org members (paginated) |
| POST | /v1/orgs/{orgId}/members/invite | Yes | Invite member by email (admin+ only) |
| PATCH | /v1/orgs/{orgId}/members/{accountId} | Yes | Change member role (admin+ only) |
| DELETE | /v1/orgs/{orgId}/members/{accountId} | Yes | Remove member (admin+ only) |
| GET | /v1/orgs/{orgId}/invitations | Yes | List pending invitations (admin+ only) |
| DELETE | /v1/orgs/{orgId}/invitations/{invId} | Yes | Revoke invitation (admin+ only) |
| POST | /v1/orgs/invitations/{invId}/accept | Yes | Accept email invitation |
| POST | /v1/orgs/{orgId}/join-link | Yes | Create or regenerate join link (admin+ only) |
| DELETE | /v1/orgs/{orgId}/join-link | Yes | Revoke join link (admin+ only) |
| GET | /v1/orgs/join/{linkId} | No | Org info for join page (name, member count) |
| POST | /v1/orgs/join/{linkId}/accept | Yes | Join organization via link |
| POST | /v1/orgs/{orgId}/domain | Yes | Set domain for verification (owner only) |
| POST | /v1/orgs/{orgId}/domain/verify | Yes | Verify domain via DNS TXT record (owner only) |
| DELETE | /v1/orgs/{orgId}/domain | Yes | Remove domain (owner only) |
| Billing | |||
| GET | /v1/billing/config | Yes | Stripe publishable key for frontend checkout |
| GET | /v1/billing/prices | Yes | Available plan prices (paid/enterprise, monthly/yearly) |
| GET | /v1/billing/balance | Yes | Customer credit balance |
| POST | /v1/billing/checkout | Yes (verified) | Create Stripe Checkout session (requires email verification) |
| GET | /v1/billing/portal | Yes (verified) | Stripe Customer Portal session URL |
| GET | /v1/billing/subscription | Yes (verified) | Current subscription plan, status, and renewal date |
| GET | /v1/billing/invoices | Yes (verified) | Invoice history (paginated) |
| GET | /v1/billing/payment-methods | Yes (verified) | List saved payment methods |
| POST | /v1/billing/payment-methods | Yes (verified) | Create SetupIntent for adding a new card |
| DELETE | /v1/billing/payment-methods/{id} | Yes (verified) | Detach payment method |
| POST | /v1/billing/payment-methods/{id}/default | Yes (verified) | Set default payment method |
| POST | /v1/billing/cancel | Yes (verified) | Cancel subscription at period end |
| POST | /v1/billing/reactivate | Yes (verified) | Reactivate cancelled subscription |
| POST | /v1/billing/upgrade-click | Yes | Track upgrade button click (analytics) |
| Backup | |||
| GET | /v1/backup/connections | Yes | List connected backup accounts (e.g. Dropbox) |
| GET | /v1/backup/connect/dropbox | Yes | Start Dropbox OAuth connection flow |
| GET | /v1/backup/callback/dropbox | No | Dropbox OAuth callback (handles redirect) |
| PATCH | /v1/backup/connections/dropbox | Yes | Update backup preferences (auto-backup, frequency) |
| DELETE | /v1/backup/connections/dropbox | Yes | Disconnect Dropbox backup |
| POST | /v1/backup/trigger | Yes | Trigger a manual backup to connected provider |
| GET | /v1/backup/jobs | Yes | List backup jobs (paginated) |
| GET | /v1/backup/jobs/{jobId} | Yes | Get backup job status and details |
| Demos | |||
| POST | /v1/skills/@{ns}/{name}/versions/{version}/demos | Yes | Upload a demo recording for a skill version |
| GET | /v1/skills/@{ns}/{name}/demos | Optional | List demos for a skill (paginated) |
| GET | /v1/demos | Optional | Browse all public demos (paginated, filterable) |
| GET | /v1/demos/{demoId} | Optional | Demo metadata (title, tool, model, star count) |
| GET | /v1/demos/{demoId}/content | Optional | Full demo recording content (messages, tool calls) |
| PATCH | /v1/demos/{demoId} | Yes | Update demo title or visibility (owner only) |
| DELETE | /v1/demos/{demoId} | Yes | Delete a demo (owner only) |
| POST | /v1/demos/{demoId}/star | Yes | Star a demo |
| DELETE | /v1/demos/{demoId}/star | Yes | Unstar a demo |
| POST | /v1/demos/{demoId}/view | No | Track a demo view (increments view counter) |
| POST | /v1/demos/{demoId}/eval-link | Yes | Link an eval result to a demo |
| DELETE | /v1/demos/{demoId}/eval-link/{evalId} | Yes | Unlink an eval result from a demo |
| POST | /v1/skills/@{ns}/{name}/pin-demo | Yes | Pin or unpin a demo on the skill page (owner only) |
| Evals & Benchmarks | |||
| POST | /v1/skills/@{ns}/{name}/versions/{version}/eval | Yes | Upload eval results for a skill version |
| GET | /v1/skills/@{ns}/{name}/eval | No | List all eval results across versions (paginated) |
| GET | /v1/skills/@{ns}/{name}/versions/{version}/eval | No | Eval results for a specific version |
| Badges | |||
| GET | /v1/badge/@{ns}/{name}/verified | No | SVG badge: verification status |
| GET | /v1/badge/@{ns}/{name}/installs | No | SVG badge: total install count |
| GET | /v1/badge/@{ns}/{name}/scan | No | SVG badge: scan report result |
| GET | /v1/badge/@{ns}/{name}/eval | No | SVG badge: latest eval pass rate |
| Security Scanning | |||
| POST | /v1/scan/github | No | Scan a public GitHub repo for security issues (returns scan ID) |
| GET | /v1/scan/github | No | Scan a GitHub repo via GET (query params: url, ref) |
| GET | /v1/scan/{scanId} | No | Get scan results by scan ID |
| GET | /v1/scan/github/bom | No | Bill of Materials for a GitHub repo |
| GET | /v1/scan/github/badge | No | SVG badge for GitHub repo scan status |
| POST | /v1/mcp/scan | No | Scan an MCP server configuration for security issues |
| Stats & Other | |||
| GET | /v1/stats | No | Platform counts: skills, publishers, scan reports |
| GET | /v1/health | No | API and database health check |
| GET | /v1/cli/version | No | Latest CLI version and download URLs |
| Demo Comments | |||
| GET | /v1/demos/{demoId}/comments | No | List comments on a demo |
| POST | /v1/demos/{demoId}/comments | Yes | Post a comment |
| DELETE | /v1/demos/{demoId}/comments/{commentId} | Yes | Delete own comment |
| POST | /v1/demos/{demoId}/comments/{commentId}/vote | Yes | Toggle upvote on a comment |
| Agents | |||
| POST | /v1/agents | Yes | Create an agent identity |
| GET | /v1/agents | Yes | List your agents (paginated) |
| GET | /v1/agents/{agentId} | Yes | Agent details and metadata |
| PATCH | /v1/agents/{agentId} | Yes | Update agent metadata |
| DELETE | /v1/agents/{agentId} | Yes | Delete an agent and all snapshots |
| POST | /v1/agents/{agentId}/snapshots | Yes | Save a snapshot (multipart: files + metadata) |
| GET | /v1/agents/{agentId}/snapshots | Yes | List snapshots (paginated) |
| GET | /v1/agents/{agentId}/snapshots/latest | Yes | Get the latest snapshot |
| GET | /v1/agents/{agentId}/snapshots/tagged/{versionTag} | Yes | Get snapshot by version tag |
| GET | /v1/agents/{agentId}/snapshots/{snapshotId} | Yes | Get a specific snapshot |
| PATCH | /v1/agents/{agentId}/snapshots/{snapshotId} | Yes | Update snapshot metadata (version_tag) |
| DELETE | /v1/agents/{agentId}/snapshots/{snapshotId} | Yes | Delete a snapshot |
| GET | /v1/agents/{agentId}/snapshots/{snapshotId}/files/* | Yes | Get file content from a snapshot |
| GET | /v1/agents/{agentId}/diff | Yes | Diff two snapshots |
| GET | /v1/agents/{agentId}/snapshots/{snapshotId}/download | Yes | Download all snapshot files |
| POST | /v1/agents/{agentId}/snapshots/{snapshotId}/scan | Yes | Scan a snapshot for security issues |
| GET | /v1/agents/{agentId}/snapshots/{snapshotId}/scan | Yes | Get scan report for a snapshot |
| Publishers | |||
| GET | /v1/publishers/{platform}/{owner} | No | Publisher profile (public) |
| GET | /v1/publishers/{platform}/{owner}/skills | No | List publisher's skills (public) |
| POST | /v1/publishers/claim | Yes | Claim a publisher identity |
| GET | /v1/account/publishers | Yes | List your claimed publishers |
| Feedback | |||
| POST | /v1/feedback | Optional | Submit feedback or bug report |
Response Format
All API responses use a standard JSON envelope.
Success
{
"ok": true,
"data": { ... },
"meta": {
"request_id": "req_...",
"timestamp": "2024-01-01T00:00:00.000Z"
}
} Paginated responses include meta.pagination with has_more and optionally next_cursor, total_count, and total_pages.
Error
{
"ok": false,
"error": {
"code": "not_found",
"message": "Skill not found.",
"status": 404,
"details": {}
},
"meta": {
"request_id": "req_...",
"timestamp": "2024-01-01T00:00:00.000Z"
}
} Error Codes
unauthorized(401) — Missing or invalid API key / sessionforbidden(403) — Insufficient permissions for the resource (also returned when email verification is required)not_found(404) — Resource does not existconflict(409) — Duplicate resource (e.g., version already exists, or max API keys reached)invalid_request(400) — Missing required fields, invalid format, or malformed request bodyinvalid_version(400) — Semver version string is invalid or does not meet requirementsvalidation_error(400) — Input failed schema or business-rule validationrate_limited(429) — Too many requests; checkRetry-Afterheaderstorage_limit_exceeded(413) — Account storage quota exceeded; upgrade to a paid planlink_revoked(410) — Share link has been revoked by the ownerlink_expired(410) — Share link has passed its expiry dateagent_limit_exceeded(403) — Maximum number of agents reached for this tiersnapshot_limit_exceeded(403) — Maximum number of snapshots reached for this agentstorage_error(500) — R2 storage operation failed; retry the requestservice_degraded(502/503) — A dependent service (email, billing) is unavailableinternal_error(500) — Unexpected server error
Rate Limits
Per-IP Sliding Window Limits
All API requests are rate-limited per IP address using a sliding window. Limits vary by endpoint group:
- Auth (
/v1/auth/*): 10 req/min - GitHub import, discover, import-url, verify (
/v1/skills/import-github,/v1/skills/import-url,/v1/skills/discover-github,*/verify): 10 req/min - Batch import (
/v1/skills/import-github/batch): 5 req/min - Agent create, scan, delete (
POST /v1/agents,*/scan,DELETE /v1/agents/*): 10 req/min - Agent snapshot upload (
POST /v1/agents/*/snapshots): 20 req/min - Billing, backup (
/v1/billing/*,/v1/backup/*): 30 req/min - Demo list (
GET /v1/skills/:ns/:name/demos): 40 req/min - Skill save (
POST /v1/skills/@{ns}/{name}): 60 req/min - Skill download (
GET /v1/skills/.../download/*): 60 req/min - Search (
GET /v1/skills/search): 60 req/min - Share, orgs, webhooks, agent read, demo detail/content/comments: 60 req/min each
- All other endpoints (
/v1/*): 120 req/min
Rate limit status is returned in response headers:
X-RateLimit-Limit— Maximum requests allowed in the windowX-RateLimit-Remaining— Requests remaining in the current windowX-RateLimit-Reset— Unix timestamp when the window resetsX-RateLimit-Window— Window identifier:"minute","hour", or"day"
When the limit is exceeded, the API returns a 429 status with a Retry-After header indicating how many seconds to wait.
Per-Hour Limits
Some sensitive endpoints have stricter per-hour limits:
- Google/GitHub sign-in: 5 req/hour each
- Email send-code (
/v1/auth/email/send-code,/v1/auth/email/register/send-code): 5 req/hour - Feedback (
POST /v1/feedback): 5 req/hour
Strict Per-Minute Limits
- Panic key revoke (
DELETE /v1/account/keys): 5 req/min
Feature-Specific Limits
- Demo upload: 20 req/min
- Demo update (
PATCH /v1/demos/:demoId): 20 req/min - Demo comments: 20 req/min (post/delete), 30 req/min (vote)
- Demo view tracking: 10 req/min
- Demo pin: 10 req/min
- Demo eval-link: 20 req/min
- Agent snapshot download: 30 req/min
- Badges (
GET /v1/badge/*): 60 req/min
Demos
Demos are recorded AI agent sessions uploaded to a skill's page. They show the skill in action and help users understand what to expect before installing.
Uploading a demo
skillsafe demo recording.json @myname/my-skill --version 1.0.0 The recording must conform to the skillsafe-demo/1 JSON schema. The demo is attached to the specified skill version and appears on the skill page. You can pin one demo per skill as the featured demo.
Browsing demos via API
GET /v1/demos?sort=views&limit=20
GET /v1/skills/@{ns}/{name}/demos
GET /v1/demos/{demoId}
GET /v1/demos/{demoId}/content The /v1/demos/:demoId/content endpoint returns the full recording (messages, tool calls, model). Use /v1/demos/:demoId for lightweight metadata only.
Evals & Benchmarks
Evals let publishers attach automated quality metrics to a skill version. Results are shown on the skill page and power the eval badge.
Uploading eval results
skillsafe eval @myname/my-skill --version 1.0.0 --eval-json results.json
skillsafe eval @myname/my-skill --version 1.0.0 --pass-rate 92.5 --test-cases 40 Pass a skill-creator eval JSON file with --eval-json, or supply raw numbers (--pass-rate, --test-cases, --pass-count). Optionally specify --model to record which model was evaluated.
Viewing eval results via API
GET /v1/skills/@{ns}/{name}/eval
GET /v1/skills/@{ns}/{name}/versions/{version}/eval Eval results include pass rate, test case counts, model name, and a regression flag if the score decreased from the previous version.
Badges
Embed live SVG badges in your README or documentation. All badge endpoints return image/svg+xml and are publicly accessible without authentication.
GET /v1/badge/@{ns}/{name}/verified — verification status
GET /v1/badge/@{ns}/{name}/installs — total install count
GET /v1/badge/@{ns}/{name}/scan — scan report result
GET /v1/badge/@{ns}/{name}/eval — latest eval pass rate Example Markdown for a README:



 Agents
Agent Identity lets you save and version your AI agent's configuration files (CLAUDE.md, .cursorrules, etc.) as immutable snapshots. Track changes over time, diff between versions, and scan snapshots for security issues.
Saving a snapshot
POST /v1/agents/:agentId/snapshots — Upload agent configuration files as a multipart form. Each snapshot gets a tree hash (SHA-256) for integrity verification. Optionally tag with a version string.
Diffing snapshots
GET /v1/agents/:agentId/diff?from={snapshotId}&to={snapshotId} — Compare two snapshots to see what files were added, removed, or modified between versions.
Scanning
POST /v1/agents/:agentId/snapshots/:snapshotId/scan — Run a security scan on a snapshot's files. Returns a scan report with findings categorized by severity.
Publishers
Publishers represent the source of imported skills — typically a GitHub user or organization. Claim your publisher identity to manage how your skills appear on SkillSafe.
Claiming a publisher
POST /v1/publishers/claim — Claim a publisher identity. For GitHub publishers, this verifies you control the GitHub account. Requires authentication.
Publisher profiles
GET /v1/publishers/:platform/:owner — Public publisher profile showing metadata, skill count, and verification status. No authentication required.
Security Model
- Integrity verification: SHA-256 tree hashes per version
- Tree hashes: Immutable per-version
- Dual verification: Independent sharer + consumer scans
- API key hashing: SHA-256 before storage
Report issues: security@skillsafe.ai