SafeSkill API Documentation

SafeSkill provides AI Agent Skill security detection capabilities through a RESTful API. Submit Skills via file upload, URL, or name for multi-dimensional scanning including static analysis, external URL threat intelligence, LLM semantic analysis, and dynamic sandbox detection.
Base URL: https://api.safeskill.io

Authentication

All API requests require an apikey parameter for authentication. Obtain your API key from the User Center after signing in.
ParameterTypeRequiredDescription
apikeystringYesYour API key for authentication

Typical Workflow

1Submit Skill (file / URL / name)
2Receive SHA256
3Poll report endpoint
4Get detection results
POST

/api/v1/scan

Submit a Skill for security scanning via file upload, URL, or Skill name.
POSThttps://api.safeskill.io/api/v1/scan
Request Parameters
ParameterTypeRequiredDescription
apikeystringYesAPI key for authentication
filefileNoSkill package file (zip, tar.gz) or SKILL.md
urlstringNoURL of a Skill in supported stores
namestringNoSkill name to search and scan (case-insensitive)
Response
JSON
{
  'response_code': 0,
  'verbose_msg': 'OK',
  'data': {
    'sha256': 'a1b2c3d4e5f67890abcdef...1234567890',
    'permalink': 'https://safeskill.io/report/{sha256}'
  }
}
ParameterTypeRequiredDescription
data.sha256stringNoSHA256 hash used for querying report
data.permalinkstringNoDirect link to online scan report
Example
cURL — file
curl "https://api.safeskill.io/api/v1/scan" \
  --form apikey='YOUR_API_KEY' \
  --form file=@linkedin-skill.zip
cURL — url
curl "https://api.safeskill.io/api/v1/scan" \
  --form apikey='YOUR_API_KEY' \
  --form url='https://clawhub.ai/ide-rea/linkedin'
cURL — name
curl "https://api.safeskill.io/api/v1/scan" \
  --form apikey='YOUR_API_KEY' \
  --form name='linkedin'
Python — file
import requests

resp = requests.post(
    "https://api.safeskill.io/api/v1/scan",
    data={"apikey": "YOUR_API_KEY"},
    files={"file": open("linkedin-skill.zip", "rb")},
)
sha256 = resp.json()["data"]["sha256"]
print(f"Submitted. SHA256: {sha256}")
Python — url / name
import requests

# Scan by URL(与 curl --form 字段一致,application/x-www-form-urlencoded)
resp = requests.post(
    "https://api.safeskill.io/api/v1/scan",
    data={"apikey": "YOUR_API_KEY", "url": "https://clawhub.ai/ide-rea/linkedin"},
)

# Scan by name
resp = requests.post(
    "https://api.safeskill.io/api/v1/scan",
    data={"apikey": "YOUR_API_KEY", "name": "linkedin"},
)

sha256 = resp.json()["data"]["sha256"]
print(f"Submitted. SHA256: {sha256}")
GET

/api/v1/report

Query a detailed scan report by the file SHA256 hash.
GEThttps://api.safeskill.io/api/v1/report?apikey=...&sha256=...
Request Parameters
ParameterTypeRequiredDescription
apikeystringYesAPI key for authentication
sha256stringYesSHA256 returned from scan endpoint
Response
JSON
{
  "response_code": 0,
  "verbose_msg": "OK",
  "data": {
    "summary": {
      "sha256": "a1b2c3d4e5f67890...",
      "sha1": "b2c3d4e5f67890ab...",
      "md5": "c3d4e5f67890abcd...",
      "file_type": "application/zip",
      "file_name": "linkedin-skill.zip",
      "threat_level": "malicious",
      "trust_score": 12,
      "is_whitelist": false,
      "multi_engines": "7/25",
      "first_seen": "2026-03-11 14:20:00",
      "last_seen": "2026-03-11 14:23:00",
      "tags": ["zip", "openclaw_skill"],
      "threat_classify": "Trojan",
      "threat_name": "ClawHavoc"
    },
    "skill_details": {
      "type": "OpenClaw Skill",
      "basic_info": {
        "skill_name": "linkedin",
        "developer": "",
        "version": "",
        "skill_type": "OpenClaw Skill",
        "description": "Use when you need to interact..."
      }
    },
    "multi_verdict": {
      "llm": "malicious",
      "static": "malicious",
      "dynamic": "unknown",
      "subfiles": "unknown",
      "external_urls": "malicious"
    },
    "external_urls_details": [
      {
        "url": "https://github.com/...",
        "source": "SKILL.md",
        "trigger_type": "manual",
        "platform": "windows",
        "threat_level": "malicious",
        "last_detection_time": "2026-02-27 17:03:25",
        "ext_info": { ... }
      }
    ],
    "subfile_details": [
      {
        "name": "data_fetcher.py",
        "sha256": "af6a70...",
        "sha1": "9b1442...",
        "md5": "eac269...",
        "size": 9626,
        "threat_level": "unknown",
        "file_type": "PYTHON"
      }
    ],
    "llm_details": {
      "summary": "High-risk behaviors detected...",
      "risk_level": "malicious",
      "risk_indicators": [
        {
          "indicator": "Downloads from unofficial repo",
          "severity": "high",
          "evidence": "https://github.com/..."
        }
      ]
    },
    "permalink": "https://safeskill.io/report/..."
  }
}
Response Fields
ParameterTypeRequiredDescription
data.summaryobjectNoFile summary (hashes, threat level, trust score, detection details)
data.summary.sha1stringNoFile SHA1 hash
data.summary.md5stringNoFile MD5 hash
data.summary.threat_levelstringNoOverall threat level for the Skill
data.summary.trust_scoreintegerNoTrust score (0–100); see Trust Score for score ranges
data.summary.first_seenstringNoFile submission time
data.summary.last_seenstringNoLast detection time
data.summary.tagsarrayNoTags list
data.skill_details.typestringNoDetected Skill type
data.skill_details.basic_infoobjectNoSkill metadata (name, developer, version, description)
data.multi_verdictobjectNoPer-dimension verdict (llm, static, dynamic, subfiles, external_urls)
data.external_urls_detailsarrayNoDetailed analysis of each external URL
data.subfile_detailsarrayNoSubfile detection details
data.llm_detailsobjectNoLLM semantic analysis results
data.permalinkstringNoOnline report link
Example
cURL
curl "https://api.safeskill.io/api/v1/report?apikey=YOUR_API_KEY&sha256=a1b2c3d4..."
Python — Scan + Poll
import requests, time

API_KEY = "YOUR_API_KEY"

# Step 1: Submit scan (file example)
resp = requests.post(
    "https://api.safeskill.io/api/v1/scan",
    data={"apikey": API_KEY},
    files={"file": open("linkedin-skill.zip", "rb")}
)
sha256 = resp.json()["data"]["sha256"]

# Step 2: Poll for report
for i in range(30):
    r = requests.get(
        "https://api.safeskill.io/api/v1/report",
        params={"apikey": API_KEY, "sha256": sha256}
    )
    data = r.json().get("data", {})
    if data.get("multi_verdict"):
        mv = data["multi_verdict"]
        print(f"LLM: {mv['llm']}, Static: {mv['static']}, Dynamic: {mv['dynamic']}")
        print(f"Trust Score: {data['summary']['trust_score']}")
        break
    time.sleep(10)

Enumerations

Threat Level Enumeration
All threat_level and risk_level fields use the following values:
ValueMeaningBadge
maliciousMalicious — confirmed as a threatMalicious
suspiciousSuspicious — potential risk identifiedSuspicious
unknownUnknown/undetermined — analyzed, insufficient evidenceUndetermined
cleanClean/benign — confirmed safeClean
Trust Score (trust_score)
trust_score is an integer from 0 to 100. It measures overall Skill trustworthiness; higher scores indicate greater safety. In general, scores of 80 or above can be considered relatively safe. Score ranges:
Score RangeMeaning
80 – 100Verified safe (80+)
71 – 79Attention needed (71–79)
41 – 70At risk (41–70)
0 – 40Confirmed malicious (0–40)
risk_indicators[].category
ParameterTypeRequiredDescription
data_theftstringNoData Theft
network_riskstringNoNetwork Risk
autonomy_abusestringNoAutonomy Abuse
rcestringNoRemote Code Execution
supply_chainstringNoSupply Chain Risk
prompt_injectionstringNoPrompt Injection
persistencestringNoPersistence
obfuscationstringNoObfuscation
social_engineeringstringNoSocial Engineering
cross_platformstringNoCross-Platform Attack
agent_hijackstringNoAgent Hijack
discovery_abusestringNoDiscovery/Recon Abuse
risk_indicators[].severity
ParameterTypeRequiredDescription
highstringNoHigh
mediumstringNoMedium
lowstringNoLow
external_urls_details[].trigger_type
ParameterTypeRequiredDescription
autostringNoAuto
manualstringNoManual
conditionalstringNoConditional
external_urls_details[].platform
ParameterTypeRequiredDescription
windowsstringNoWindows
macosstringNomacOS
linuxstringNoLinux
allstringNoAll platforms

Field Quick Reference

Report response (data) field paths, types, and descriptions:
Field pathTypeDescription
data (top-level)
summaryobjectFile summary
skill_detailsobjectAI Agent detection details
multi_verdictobjectPer-dimension verdict (llm, static, dynamic, subfiles, external_urls)
external_urls_detailsarrayDetailed analysis of each external URL
subfile_detailsarraySubfile detection details (name, hashes, size, threat_level, file_type)
llm_detailsobjectLLM semantic analysis results
permalinkstringOnline report link
summary
summary.sha256stringFile SHA256
summary.sha1stringFile SHA1
summary.md5stringFile MD5
summary.file_typestringFile type
summary.file_namestringFile name
summary.threat_levelstringOverall threat level (static + AV + dynamic)
summary.trust_scoreintegerTrust score (0–100)
summary.first_seenstringSubmission time
summary.last_seenstringLast detection time
summary.tagsarrayTags list
skill_details
skill_details.typestringDetected Skill type
skill_details.basic_infoobjectBasic info
multi_verdict
multi_verdict.llmstringLLM dimension verdict
multi_verdict.staticstringStatic analysis verdict
multi_verdict.dynamicstringDynamic sandbox verdict
multi_verdict.subfilesstringSubfiles dimension verdict
multi_verdict.external_urlsstringExternal URLs verdict
external_urls_details
external_urls_details[].urlstringExternal URL
external_urls_details[].threat_levelstringURL threat conclusion
external_urls_details[].last_detection_timestringDetection time
subfile_details
subfile_details[].namestringSubfile name
subfile_details[].sha256stringSubfile SHA256
subfile_details[].sha1stringSubfile SHA1
subfile_details[].md5stringSubfile MD5
subfile_details[].sizeintegerSubfile size (bytes)
subfile_details[].threat_levelstringSubfile threat level
subfile_details[].file_typestringSubfile type
llm_details
llm_details.analyzed_atstringAnalysis time
llm_details.llm_modelstringLLM model
llm_details.summarystringSummary
llm_details.risk_levelstringRisk level
llm_details.intent_reconstructionobjectIntent reconstruction
llm_details.intent_reconstruction.intent_confidenceintegerIntent consistency (0–100); higher values mean stronger alignment
llm_details.extracted_iocsobjectIndicators extracted from the file; not necessarily malicious—use with caution.
llm_details.risk_indicators[]arrayRisk indicators
llm_details.risk_indicators[].indicatorstringRisk description
llm_details.risk_indicators[].categorystringRisk category
llm_details.risk_indicators[].severitystringSeverity: high / medium / low
llm_details.risk_indicators[].evidencestringEvidence
llm_details.platform_analysisobjectPlatform analysis (windows/macos/linux)

Response Codes

The API uses standardized response_code. Check response_code and verbose_msg in every response.
Response CodeVerbose MsgDescription
0OKSuccess
2No DataNo data
3In ProgressTask in progress
-1Invalid Account StatusInvalid account status
-1Invalid Access IPInvalid access IP: {actual IP}
-1Invalid API KeyInvalid API key; please enter a correct API key
-1Invalid Key StatusAPI key status invalid
-1Invalid Parameter: {parameter}Invalid API parameter: {parameter name}
-1No Access to API MethodNo permission to access the API method
-1Expired API KeyAPI key expired
-1Empty FileUploaded empty file
-1File Size Too LargeUploaded file too large
-1File Name Too LongUploaded file name too long
-2Invalid API MethodInvalid API method
-3Required:{}Required request parameter missing: specific missing item(s)
-4Frequent LimitationAccess rate limit triggered
-4BeyondLimitationAccess limit exceeded
-5System ErrorSystem error

Complete Response Examples

Malicious Skill
JSON
{
  "response_code": 0,
  "verbose_msg": "OK",
  "data": {
    "summary": {
      "sha256": "a1b2c3d4e5f67890abcdef...",
      "sha1": "b2c3d4e5f67890ab...",
      "md5": "c3d4e5f67890abcd...",
      "file_type": "application/zip",
      "file_name": "linkedin-skill.zip",
      "threat_level": "malicious",
      "trust_score": 12,
      "first_seen": "2026-03-11 14:20:00",
      "last_seen": "2026-03-11 14:23:00",
      "tags": ["zip", "openclaw_skill"],
    },
    "skill_details": {
      "type": "OpenClaw Skill",
      "basic_info": { "skill_name": "linkedin", ... }
    },
    "multi_verdict": {
      "llm": "malicious",
      "static": "malicious",
      "dynamic": "unknown",
      "subfiles": "unknown",
      "external_urls": "malicious"
    },
    "external_urls_details": [ ... ],
    "subfile_details": [
      { "name": "data_fetcher.py", "sha256": "af6a70...", "size": 9626, "threat_level": "unknown", "file_type": "PYTHON" }
    ],
    "llm_details": {
      "risk_level": "malicious",
      "risk_indicators": [ ... ]
    }
  }
}
Clean Skill
JSON
{
  "response_code": 0,
  "verbose_msg": "OK",
  "data": {
    "summary": {
      "sha256": "f0e1d2c3b4a59678...",
      "sha1": "e1d2c3b4a5967801...",
      "md5": "d2c3b4a596780123...",
      "file_type": "application/zip",
      "file_name": "weather-skill.zip",
      "threat_level": "clean",
      "trust_score": 92,
      "first_seen": "2026-03-10 09:15:00",
      "last_seen": "2026-03-10 09:18:00",
      "tags": ["zip", "openclaw_skill"],
    },
    "skill_details": {
      "type": "OpenClaw Skill",
      "basic_info": { ... }
    },
    "multi_verdict": {
      "llm": "clean",
      "static": "clean",
      "dynamic": "clean",
      "subfiles": "clean",
      "external_urls": "clean"
    },
    "external_urls_details": [],
    "subfile_details": [],
    "llm_details": {
      "risk_level": "clean",
      "risk_indicators": []
    }
  }
}