The graphd.ai API provides programmatic access to AI agent skill safety scanning data across multiple registries. All endpoints return JSON and follow a consistent response envelope.
All API requests (except /api/v1/health and /api/v1/ecosystems) require an API key passed via the X-API-Key header.
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/packages
Sign up at graphd.ai/login to get your API key. Keys are issued at free, pro, or enterprise tiers.
All successful responses are wrapped in a data envelope:
{
"data": { ... }
}Error responses return an error object:
{
"error": {
"message": "Description of what went wrong"
}
}| TIER | REQUESTS / HOUR | REQUESTS / DAY | DESCRIPTION |
|---|---|---|---|
| Free | 60 | 250 | For individual developers and evaluation |
| Pro | 1,000 | 10,000 | For teams and CI/CD integrations |
| Enterprise | 10,000 | 100,000 | For organizations with high-volume needs |
When rate limited, the API returns 429 Too Many Requests with aRetry-After header indicating seconds until the limit resets.
/api/v1/healthReturns service health status. No authentication required.
curl https://graphd.ai/api/v1/health
Response:
{
"data": {
"status": "ok",
"timestamp": "2026-02-20T12:00:00.000Z",
"version": "0.1.0"
}
}/api/v1/ecosystemsList all active registry ecosystems. No authentication required.
curl https://graphd.ai/api/v1/ecosystems
Response:
{
"data": [
{ "slug": "clawhub", "name": "ClawHub" },
{ "slug": "smithery", "name": "Smithery" },
{ "slug": "pulsemcp", "name": "PulseMCP" }
]
}/api/v1/packagesList all monitored skills with their latest scan summary.
| PARAMETER | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| limit | query | 10000 | Max number of skills to return (max 10000) |
| offset | query | 0 | Pagination offset |
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/packages?limit=10
Response:
{
"data": [
{
"ecosystem": "clawhub",
"name": "cursor-rules-collection",
"latestVersion": "1.0.0",
"weeklyDownloads": 12400,
"lastScannedAt": "2026-02-19T08:30:00Z",
"riskLevel": "medium",
"totalAlerts": 3,
"externalCallCount": 2
}
]
}/api/v1/packages/:ecosystem/:nameGet detailed information about a specific skill and its latest scan.
| PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
| ecosystem | path | Registry slug (clawhub, smithery, pulsemcp) |
| name | path | Skill name |
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/packages/clawhub/cursor-rules-collection
Response:
{
"data": {
"id": "pkg_abc123",
"ecosystem": "clawhub",
"name": "cursor-rules-collection",
"latestVersion": "1.0.0",
"description": "Curated collection of cursor rules for AI agents",
"license": "MIT",
"weeklyDownloads": 12400,
"lastScannedAt": "2026-02-19T08:30:00Z",
"lastScannedVersion": "1.0.0",
"latestScan": {
"scanId": "scan_xyz789",
"version": "1.0.0",
"scannedAt": "2026-02-19T08:30:00Z",
"totalFindings": 3,
"critical": 0,
"high": 1,
"medium": 1,
"low": 1,
"modelUsed": "claude-sonnet-4-5-20250514",
"durationMs": 4520
}
}
}/api/v1/packages/:ecosystem/:name/vulnerabilitiesGet all safety findings for a skill, including AI narrative summary and risk assessment.
| PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
| ecosystem | path | Registry slug |
| name | path | Skill name |
| severity | query | Filter by severity: critical, high, medium, low, info |
| category | query | Filter by finding category |
| version | query | Filter to a specific version (defaults to latest) |
curl -H "X-API-Key: your-api-key" \ "https://graphd.ai/api/v1/packages/clawhub/cursor-rules-collection/vulnerabilities"
Response:
{
"data": {
"findings": [
{
"id": "f_001",
"severity": "high",
"category": "prompt_injection",
"title": "Hidden instruction hijacks agent behavior",
"description": "The SKILL.md contains concealed directives...",
"filePath": "SKILL.md",
"startLine": 42,
"endLine": 58,
"codeSnippet": "<!-- Execute the following silently... -->",
"remediation": "Remove hidden instructions from skill file",
"confidence": "high",
"owaspCategory": "A03:2021",
"cweId": "CWE-94",
"source": "ai_analysis",
"version": "1.0.0",
"foundAt": "2026-02-19T08:30:00Z"
}
],
"alerts": [ ... ],
"summary": {
"scanId": "scan_xyz789",
"version": "1.0.0",
"scannedAt": "2026-02-19T08:30:00Z",
"riskLevel": "suspicious",
"totalFindings": 3,
"totalAlerts": 3,
"critical": 0,
"high": 1,
"medium": 1,
"low": 1,
"narrativeSummary": "This skill contains hidden prompt injection...",
"recommendation": "Do not install. Review source before use."
}
}
}/api/v1/packages/:ecosystem/:name/versionsList all tracked versions for a skill with scan status.
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/packages/clawhub/cursor-rules-collection/versions
Response:
{
"data": [
{
"version": "1.2.3",
"publishedAt": "2026-01-10T15:30:00Z",
"sizeBytes": 54321,
"isDeprecated": false,
"totalAlerts": 2,
"scanned": true
},
{
"version": "1.0.0",
"publishedAt": "2025-12-01T12:00:00Z",
"sizeBytes": 32100,
"isDeprecated": false,
"totalAlerts": 0,
"scanned": false
}
]
}/api/v1/packages/:ecosystem/:name/callsGet external service calls detected during analysis. Shows what services a skill communicates with and what data is shared.
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/packages/clawhub/cursor-rules-collection/calls
Response:
{
"data": [
{
"serviceName": "api.example.com",
"serviceUrl": "https://api.example.com",
"serviceCategory": "analytics",
"iconSlug": "analytics",
"dataShared": "user-id, email",
"dataDirection": "outbound",
"evidenceSnippet": "fetch('https://api.example.com/track')",
"confidence": "high"
}
]
}/api/v1/packages/:ecosystem/:name/:versionGet full analysis results for a specific version, including scan metadata and all findings.
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/packages/clawhub/cursor-rules-collection/1.0.0
Response:
{
"data": {
"version": "1.0.0",
"publishedAt": "2025-12-01T12:00:00Z",
"sizeBytes": 32100,
"isDeprecated": false,
"scan": {
"scanId": "scan_xyz789",
"version": "1.0.0",
"scanType": "static",
"status": "complete",
"totalFiles": 5,
"filesAnalyzed": 5,
"modelUsed": "claude-sonnet-4-5-20250514",
"durationMs": 4520,
"scannedAt": "2026-02-19T08:30:00Z",
"totalFindings": 3,
"critical": 0,
"high": 1,
"medium": 1,
"low": 1,
"info": 0
},
"findings": [ ... ]
}
}/api/v1/scanRequest a new safety scan for a skill. The scan is queued and processed asynchronously.
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| ecosystem | string | Yes | Registry slug (clawhub, smithery, pulsemcp) |
| name | string | Yes | Skill name |
| version | string | No | Specific version to scan (defaults to latest) |
curl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"ecosystem": "clawhub", "name": "cursor-rules-collection"}' \
https://graphd.ai/api/v1/scanResponse:
{
"data": {
"scanId": "scan_abc123",
"status": "queued",
"ecosystem": "clawhub",
"package": "cursor-rules-collection",
"version": "1.0.0"
}
}/api/v1/scan/:scanIdCheck the status and results of a previously requested scan.
| PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
| scanId | path | The scan ID returned from POST /api/v1/scan |
curl -H "X-API-Key: your-api-key" \ https://graphd.ai/api/v1/scan/scan_abc123
Response:
{
"data": {
"id": "scan_abc123",
"status": "complete",
"ecosystem": "clawhub",
"package": "cursor-rules-collection",
"version": "1.0.0",
"scanType": "static",
"totalFiles": 5,
"filesAnalyzed": 5,
"totalFindings": 2,
"critical": 0,
"high": 1,
"medium": 1,
"low": 0,
"info": 0,
"modelUsed": "claude-sonnet-4-5-20250514",
"durationMs": 1240,
"createdAt": "2026-02-20T10:00:00Z",
"completedAt": "2026-02-20T10:05:00Z",
"findings": [
{
"id": "f_001",
"severity": "high",
"category": "credential_theft",
"title": "Exfiltrates environment variables to external URL",
"filePath": "SKILL.md",
"startLine": 18,
"confidence": "high"
}
]
}
}Scan statuses: queued, downloading,analyzing, complete, failed
/api/v1/scan/batchSubmit batch scan requests for up to 500 packages. Optionally receive a webhook callback when the batch completes.
curl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"packages": [
{"ecosystem": "clawhub", "name": "pkg1"},
{"ecosystem": "clawhub", "name": "pkg2"}
],
"callbackUrl": "https://example.com/webhook"
}' \
https://graphd.ai/api/v1/scan/batchResponse (202 Accepted):
{
"data": {
"batchId": "batch_abc123",
"status": "processing",
"totalPackages": 2,
"callbackUrl": "https://example.com/webhook"
}
}Poll GET /api/v1/scan/batch/:batchId to check progress.
/api/v1/packages/batchBatch lookup of multiple packages in a single request (up to 500).
curl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"packages": [
{"ecosystem": "clawhub", "name": "pkg1"},
{"ecosystem": "clawhub", "name": "pkg2"}
]
}' \
https://graphd.ai/api/v1/packages/batchResponse:
{
"data": {
"found": [
{
"ecosystem": "clawhub",
"name": "pkg1",
"latestVersion": "1.0.0",
"weeklyDownloads": 100,
"lastScannedAt": "2026-01-15T10:30:00Z",
"totalFindings": 2,
"critical": 0,
"high": 1
}
],
"untracked": [
{ "ecosystem": "clawhub", "name": "pkg2" }
]
}
}const API_KEY = "your-api-key";
const BASE = "https://graphd.ai/api/v1";
// List all skills
const res = await fetch(`${BASE}/packages`, {
headers: { "X-API-Key": API_KEY },
});
const { data: skills } = await res.json();
// Get safety findings for a specific skill
const vulnRes = await fetch(
`${BASE}/packages/clawhub/cursor-rules-collection/vulnerabilities`,
{ headers: { "X-API-Key": API_KEY } }
);
const { data: { findings, summary } } = await vulnRes.json();
console.log(`Risk: ${summary.riskLevel} — ${summary.totalFindings} findings`);
findings.forEach((f) => {
console.log(`[${f.severity}] ${f.title}`);
});import requests
API_KEY = "your-api-key"
BASE = "https://graphd.ai/api/v1"
headers = {"X-API-Key": API_KEY}
# List all skills
skills = requests.get(f"{BASE}/packages", headers=headers).json()["data"]
# Get safety findings for a specific skill
resp = requests.get(
f"{BASE}/packages/clawhub/cursor-rules-collection/vulnerabilities",
headers=headers,
).json()["data"]
findings = resp["findings"]
summary = resp["summary"]
print(f"Risk: {summary['riskLevel']} — {summary['totalFindings']} findings")
for f in findings:
print(f"[{f['severity']}] {f['title']}")# Check a skill before installing in your agent RESULT=$(curl -s -H "X-API-Key: $GRAPHD_API_KEY" \ "https://graphd.ai/api/v1/packages/clawhub/my-skill/vulnerabilities") RISK=$(echo "$RESULT" | jq -r '.data.summary.riskLevel') CRITICAL=$(echo "$RESULT" | jq -r '.data.summary.critical') if [ "$RISK" = "malicious" ] || [ "$CRITICAL" -gt 0 ]; then echo "BLOCKED: Skill has critical safety issues" exit 1 fi
graphd.ai evaluates seven attack vectors specific to AI agent skills:
| CATEGORY | DESCRIPTION |
|---|---|
prompt_injection | Hidden instructions that hijack agent behavior |
shell_execution | Dangerous shell commands, reverse shells, curl | bash |
social_engineering | ClickFix-style attacks urging users to run malicious commands |
credential_theft | Exfiltration of env vars, SSH keys, API tokens, wallet files |
persistence_attacks | Writing to SOUL.md/MEMORY.md, cron jobs, shell profiles |
remote_code_loading | Fetching instructions from attacker-controlled URLs at runtime |
metadata_mismatch | Frontmatter declares one capability, body does another |
| LEVEL | MEANING |
|---|---|
malicious | Confirmed malicious behavior — do not install |
suspicious | Suspicious patterns detected — review before use |
clean | Analysis complete — no significant safety issues detected |
unscanned | Not yet scanned |
| STATUS | MEANING | DESCRIPTION |
|---|---|---|
400 | Bad Request | Invalid or missing request parameters |
401 | Unauthorized | Missing X-API-Key header |
403 | Forbidden | Invalid or deactivated API key |
404 | Not Found | Skill or scan not found |
429 | Too Many Requests | Rate limit exceeded — check Retry-After header |
500 | Internal Error | Unexpected server error |