api-reference
Skill0 starsChanged 9 months agoMITView on GitHub
Complete HTTP API reference for Caves with authentication, endpoints, and curl examples. Use when users need direct API access with API keys instead of MCP tools.
- Reads credentials
- Sends data out
3 other projects use a version of this.
Adopted by
Most recently taken up by
- raphaeltm/simple-agent-managertheir own version, first seen Nov 7, 2026
- matrixorigin/Memoriatheir own version, first seen Oct 8, 2026
- littlebearapps/pitchdocstheir own version, first seen Mar 15, 2026
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- matrixorigin/Memoria★ 624same name
- raphaeltm/simple-agent-manager★ 69same name
- littlebearapps/pitchdocs★ 8same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository6 other files it gives its agents.
- agent-signupSkill
- caves-knowledgeSkill
- chat-to-cavesSkill
- content-to-cavesSkill
- crypto-subscribeSkill
- perspective-resolverSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
34 rules. 0 are common, 30 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
30
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 26
Don't need custom HTTP integration
- Distinctive: line 27
Prefer built-in tool abstractions
- Distinctive: line 55
All authenticated endpoints support two authentication methods:
- Distinctive: line 140
Create a new perspective with a username.
- Distinctive: line 187
Search for caves by query string with optional perspective filtering.
- Very specific: line 334
Use md (default) when: Context window is limited, human readability preferred, overview needed
- Very specific: line 335
Use json when: Programmatic processing required, need full metadata (timestamps, values), building analytics
- Very specific: line 336
Use ic when: InterConnected format compatibility needed
- Distinctive: line 411
Create connections between caves (batch operation).
- Distinctive: line 422
Important: Use lowercase for all tags EXCEPT perspective IDs (Ethereum addresses starting with 0x).
- Distinctive: line 487
403 Forbidden: Not authorized to use this pId
- Distinctive: line 492
Important for Agents: Before creating connections programmatically, verify the user/perspective has sufficient fire balance.
- Distinctive: line 498
Remove a connection between caves.
- Distinctive: line 509
Important: Use lowercase for all tags EXCEPT perspective IDs.
- Distinctive: line 620
400 Bad Request: No tags provided or invalid matchMode
- Distinctive: line 710
Call POST /uploads/text directly with your API key
- Distinctive: line 712
Add meaningful tags with POST /tags for discoverability
- Distinctive: line 715
Call POST /oauth/upload-token to get temporary token
- Distinctive: line 716
Use token with POST /uploads/text within expiration window
- Very specific: line 789
Next Steps: Use POST /tags to add meaningful tags to organize this content (e.g., topics, categories, sources).
- Distinctive: line 801
Create a short-lived upload token for large text files (>=100KB).
- Distinctive: line 805
When to Use: Use this endpoint when uploading text content >= 100KB.
- Distinctive: line 839
Call this endpoint to get upload token
- Distinctive: line 840
Use token immediately with POST /uploads/text
- Distinctive: line 914
When using the API directly, call the appropriate endpoint based on your input type.
- Distinctive: line 985
Implementation Tip: When building automated subscription flows, poll step 5 until status changes to 'completed' or 'failed'.
- Distinctive: line 991
Authentication: Not required (public endpoint)
- Distinctive: line 1020
Create a crypto payment session.
- Distinctive: line 1096
403 Forbidden: Not authorized to perform this action
- Distinctive: line 1105
All error responses follow this format:
- Distinctive: line 1161
Use batch operations (POST /tags for multiple connections)
- Distinctive: line 1247
Update all services using the key
- Distinctive: line 1396
No API key management
- Distinctive: line 1402
No custom integration needed
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Caves HTTP API Reference
Complete reference for direct HTTP access to the Caves knowledge graph system using API keys.
Overview
This reference documents the Caves HTTP API for developers who need programmatic access outside the MCP ecosystem. All endpoints require authentication via API key.
When to Use Direct API
Use Direct HTTP API when:
- Building custom integrations outside Claude Code
- Creating scripts or automation tools
- Working in environments without MCP support
- Need API key authentication (not OAuth)
- Integrating with external systems or services
Use MCP Tools when:
- Working in Claude Desktop or Claude Code
- Want OAuth convenience and security
- Don't need custom HTTP integration
- Prefer built-in tool abstractions
Prerequisites
API Key Required: You must have a Caves API key to use these endpoints.
Getting an API Key
Option 1: Agent Signup Skill (Recommended for AI agents)
Use the agent-signup skill in Claude Code:
"I need to create a Caves account"Option 2: Web Interface (Recommended for humans)
1. Visit https://itscaves.com
2. Sign up for an account
3. Navigate to https://itscaves.com/account
4. Generate API key in account settingsAPI Key Format: cav_ followed by 64 hexadecimal characters
Example: cav_abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567890abcd
Authentication
All authenticated endpoints support two authentication methods:
Option 1: Authorization Bearer Header (Recommended)
Authorization: Bearer cav_abc123def456...Option 2: X-API-Key Header
X-API-Key: cav_abc123def456...Both methods work identically - use whichever fits your application better.
Base URL
https://its.itscaves.comSecurity Best Practices
- ✅ Store API keys in environment variables
- ✅ Use secure password managers
- ✅ Never commit to version control
- ✅ Never share publicly or in screenshots
- ✅ Rotate keys regularly
- ❌ Don't hardcode in source files
- ❌ Don't expose in client-side code
API Endpoints
Perspective Management
Perspectives (also called "shadows" or "pIds") are user identities in the Caves system. Each perspective has a unique Ethereum-style address and can create its own knowledge graph.
GET /user/pIds
Get all perspectives for the authenticated user.
Authentication: Required
Parameters: None
Request Example:
curl -X GET "https://its.itscaves.com/user/pIds" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK):
{
"fire": 100,
"earnedFire": 500,
"nextFireUpdate": "2026-02-28T12:00:00Z",
"pIds": [
{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"username": "my-perspective",
"tagline": "My knowledge graph",
"profilePic": "https://..."
}
]
}Response Fields:
fire(number): Current fire balance (Caves currency)earnedFire(number): Total fire earned historicallynextFireUpdate(string): ISO timestamp when fire regeneratespIds(array): List of user's perspectivespId(string): Ethereum-style address (perspective ID)username(string): Human-readable perspective nametagline(string): Optional descriptionprofilePic(string): Avatar URL
Error Responses:
- 401 Unauthorized: Invalid or missing API key
- 500 Internal Server Error: Server error
POST /p/create
Create a new perspective with a username.
Authentication: Required
Parameters:
username(string, required): Username for the new perspective (trimmed of whitespace)
Request Example:
curl -X POST "https://its.itscaves.com/p/create" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"username": "my-new-perspective"
}'Response (200 OK):
{
"pId": "0xF2b3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0b1",
"username": "my-new-perspective",
"profilePic": "https://...",
"createdAt": "2026-02-27T12:00:00Z"
}Response Fields:
pId(string): Newly generated perspective ID (Ethereum address)username(string): The username providedprofilePic(string): Randomly assigned profile picture URLcreatedAt(string): ISO timestamp of creation
Error Responses:
- 400 Bad Request: Missing username or invalid format
- 401 Unauthorized: Invalid API key
- 409 Conflict: Username already taken
- 500 Internal Server Error: Server error
Cave Operations
Caves (also called "tags") are the nodes in the knowledge graph. Each cave represents a concept, topic, or piece of content.
GET /search
Search for caves by query string with optional perspective filtering.
Authentication: Required
Parameters:
s(string, required): Search query (case-insensitive, automatically lowercased)pIds(string, optional): Comma-separated list of perspective IDs to filter by
Note: Filtering by pIds is more computationally intensive. Only use when specifically needed.
Request Example:
# Basic search
curl -X GET "https://its.itscaves.com/search?s=javascript" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# Search filtered by perspectives
curl -X GET "https://its.itscaves.com/search?s=javascript&pIds=0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0,0xF2b3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0b1" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK):
[
{
"tag": "javascript",
"similarity": 1.0,
"fire": 150,
"origin caves": 12,
"children": 25
},
{
"tag": "javascript frameworks",
"similarity": 0.85,
"fire": 75,
"origin caves": 5,
"children": 8
}
]Response Fields (array of objects):
tag(string): Cave/tag namesimilarity(number): Relevance score (0-1)fire(number): Total fire (YES votes) for this caveorigin caves(number): Number of parent connectionschildren(number): Number of child connections
Error Responses:
- 400 Bad Request: Missing search query
- 401 Unauthorized: Invalid API key
- 500 Internal Server Error: Server error
GET /tags/{parentCave}
Get subcaves (children) for a specified parent cave with optional personalization.
Authentication: Required
Path Parameters:
parentCave(string, required): URL-encoded parent cave name
Query Parameters:
pId(string, optional): Perspective ID for personalized related caves
Request Example:
# Get subcaves without personalization
curl -X GET "https://its.itscaves.com/tags/programming" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# Get subcaves with personalization
curl -X GET "https://its.itscaves.com/tags/programming?pId=0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK):
{
"items": [
{
"tag": "javascript",
"yes": 5,
"no": 0,
"updatedAt": "2026-02-27T10:30:00Z",
"children": 3
},
{
"tag": "python",
"yes": 3,
"no": 0,
"updatedAt": "2026-02-27T09:15:00Z",
"children": 1
}
],
"caves": [
{
"tag": "computer science",
"yes": 7,
"no": 0,
"updatedAt": "2026-02-26T14:20:00Z"
}
]
}Response Fields:
items(array): Child caves of the parenttag(string): Cave nameyes(number): YES votes for this connectionno(number): NO votes for this connectionupdatedAt(string): ISO timestamp of last updatechildren(number): Number of children this cave has
caves(array): Related caves (when pId provided)- Same fields as items
Error Responses:
- 400 Bad Request: Invalid parent cave name
- 401 Unauthorized: Invalid API key
- 404 Not Found: Parent cave doesn't exist
- 500 Internal Server Error: Server error
GET /tags/pId/{pId}
Fetch the complete knowledge graph for a perspective.
Authentication: Required
Path Parameters:
pId(string, required): Perspective ID
Query Parameters:
format(string, optional): Output format -json,ic, ormd(default:md)md: Hierarchical markdown (recommended - most compressed)json: Flat array of connectionsic: InterConnected format
since(string|number, optional): Filter connections after this date/timestamp
Format Selection Guide:
- Use
md(default) when: Context window is limited, human readability preferred, overview needed - Use
jsonwhen: Programmatic processing required, need full metadata (timestamps, values), building analytics - Use
icwhen: InterConnected format compatibility needed
Why MD Format Saves Context: Markdown format uses hierarchical indentation instead of repeating parent names in every connection, reducing token usage by ~60-70% for large graphs.
Example Comparison:
- JSON: 5000 tokens for 200 connections
- MD: 1500 tokens for same 200 connections
Request Example:
# Get graph in markdown format (default)
curl -X GET "https://its.itscaves.com/tags/pId/0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# Get graph in JSON format
curl -X GET "https://its.itscaves.com/tags/pId/0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0?format=json" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# Filter connections since specific date
curl -X GET "https://its.itscaves.com/tags/pId/0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0?format=json&since=2026-02-01" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK) - Markdown Format:
# programming
- javascript
- typescript
- react
- python
- django
- flaskResponse (200 OK) - JSON Format:
[
{
"parent": "programming",
"child": "javascript",
"value": 1,
"timestamp": "2026-02-27T10:00:00Z"
},
{
"parent": "javascript",
"child": "typescript",
"value": 1,
"timestamp": "2026-02-27T10:05:00Z"
}
]Response Fields (JSON format):
parent(string): Parent cave namechild(string): Child cave namevalue(number): 1 for YES, 0 for NOtimestamp(string): ISO timestamp of connection creation
Error Responses:
- 400 Bad Request: Invalid pId or format
- 401 Unauthorized: Invalid API key
- 404 Not Found: Perspective doesn't exist
- 500 Internal Server Error: Server error
Connection Management
Connections define the hierarchical relationships between caves in the knowledge graph.
POST /tags
Create connections between caves (batch operation).
Authentication: Required
Parameters:
pId(string, required): Perspective ID to use for creating connectionsconnections(array, required): Array of connection objectsparent(string): Parent cave/tag (more general concept)child(string): Child cave/tag (more specific concept)value(boolean|number):true/1for YES,false/0for NO
Important: Use lowercase for all tags EXCEPT perspective IDs (Ethereum addresses starting with 0x).
Request Example:
curl -X POST "https://its.itscaves.com/tags" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"connections": [
{
"parent": "programming",
"child": "javascript",
"value": true
},
{
"parent": "javascript",
"child": "typescript",
"value": 1
},
{
"parent": "programming",
"child": "bad-language",
"value": false
}
]
}'Response (200 OK):
{
"success": true,
"created": 2,
"existed": 1,
"connections": [
{
"parent": "programming",
"child": "javascript",
"status": "created"
},
{
"parent": "javascript",
"child": "typescript",
"status": "created"
},
{
"parent": "programming",
"child": "bad-language",
"status": "existed",
"value": false
}
]
}Response Fields:
success(boolean): Overall operation successcreated(number): Number of new connections createdexisted(number): Number of connections that already existedconnections(array): Status of each connection
Error Responses:
- 400 Bad Request: Missing pId, invalid connections array, or malformed data
- 401 Unauthorized: Invalid API key
- 403 Forbidden: Not authorized to use this pId
- 500 Internal Server Error: Server error
Cost: Creating connections consumes fire (Caves currency). Ensure sufficient balance.
Important for Agents: Before creating connections programmatically, verify the user/perspective has sufficient fire balance. Check fire balance via GET /user/pIds endpoint.
DELETE /tags
Remove a connection between caves.
Authentication: Required
Parameters:
pId(string, required): Perspective ID to use for removing connectionconnection(object, required): Connection to removeparent(string): Parent cave/tagchild(string): Child cave/tagvalue(boolean|number):true/1for YES,false/0for NO
Important: Use lowercase for all tags EXCEPT perspective IDs.
Request Example:
curl -X DELETE "https://its.itscaves.com/tags" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"connection": {
"parent": "programming",
"child": "javascript",
"value": true
}
}'Response (200 OK):
{
"success": true,
"removed": true,
"connection": {
"parent": "programming",
"child": "javascript",
"value": 1
}
}Response Fields:
success(boolean): Operation successremoved(boolean): Whether connection was removedconnection(object): The removed connection details
Error Responses:
- 400 Bad Request: Missing pId, invalid connection, or malformed data
- 401 Unauthorized: Invalid API key
- 403 Forbidden: Not authorized to use this pId
- 404 Not Found: Connection doesn't exist
- 500 Internal Server Error: Server error
Discovery Operations
Discovery endpoints help find perspectives that have interacted with specific caves or connections.
GET /tags/pids/{tag1}/{tag2}/...
Get all perspective IDs that have made connections with one or more tags.
Authentication: Required
Path Parameters:
{tag1}/{tag2}/...(strings, required): URL-encoded tag names (can be 1 or more)
Query Parameters:
matchMode(string, optional):all(default) oranyall: Returns PIDs connected to ALL tags (intersection)any: Returns PIDs connected to ANY tags (union)
Request Example:
# PIDs connected to a single tag
curl -X GET "https://its.itscaves.com/tags/pids/javascript" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# PIDs connected to ALL specified tags (intersection)
curl -X GET "https://its.itscaves.com/tags/pids/javascript/typescript?matchMode=all" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# PIDs connected to ANY specified tags (union)
curl -X GET "https://its.itscaves.com/tags/pids/javascript/python/ruby?matchMode=any" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK):
{
"pIds": [
{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"username": "developer-1",
"connections": 15
},
{
"pId": "0xF2b3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0b1",
"username": "developer-2",
"connections": 8
}
],
"totalPids": 2,
"tags": ["javascript", "typescript"],
"matchMode": "all"
}Response Fields:
pIds(array): List of matching perspectivespId(string): Perspective IDusername(string): Perspective usernameconnections(number): Number of connections to matched tags
totalPids(number): Count of matching perspectivestags(array): The tags that were searchedmatchMode(string): The match mode used
Error Responses:
- 400 Bad Request: No tags provided or invalid matchMode
- 401 Unauthorized: Invalid API key
- 500 Internal Server Error: Server error
GET /tags/pids/connection/{parent}/{child}
Get all perspective IDs that have made a specific connection between two caves.
Authentication: Required
Path Parameters:
{parent}(string, required): URL-encoded parent cave name{child}(string, required): URL-encoded child cave name
Query Parameters:
vote(string, optional):yes(default) ornoyes: Find PIDs that voted YES on this connectionno: Find PIDs that voted NO on this connection
Request Example:
# PIDs that agree on this connection (YES votes)
curl -X GET "https://its.itscaves.com/tags/pids/connection/programming/javascript?vote=yes" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"
# PIDs that disagree on this connection (NO votes)
curl -X GET "https://its.itscaves.com/tags/pids/connection/programming/javascript?vote=no" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK):
{
"pIds": [
{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"username": "developer-1",
"timestamp": "2026-02-27T10:00:00Z"
},
{
"pId": "0xF2b3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0b1",
"username": "developer-2",
"timestamp": "2026-02-26T15:30:00Z"
}
],
"totalPids": 2,
"connection": {
"parent": "programming",
"child": "javascript",
"vote": "yes"
}
}Response Fields:
pIds(array): List of matching perspectivespId(string): Perspective IDusername(string): Perspective usernametimestamp(string): When connection was made
totalPids(number): Count of matching perspectivesconnection(object): The connection that was queriedparent(string): Parent cavechild(string): Child cavevote(string): Vote type queried
Error Responses:
- 400 Bad Request: Missing parent/child or invalid vote
- 401 Unauthorized: Invalid API key
- 404 Not Found: Connection doesn't exist
- 500 Internal Server Error: Server error
Content Management
Manage uploaded content and fetch resources from IPFS or URLs.
POST /uploads/text
Upload text content to IPFS and associate with your perspective.
Authentication: Required
Upload Workflow:
Small Files (<100KB):
- Call POST /uploads/text directly with your API key
- Content uploads to IPFS and auto-tags under 'uploads'
- Add meaningful tags with POST /tags for discoverability
Large Files (>=100KB):
- Call POST /oauth/upload-token to get temporary token
- Use token with POST /uploads/text within expiration window
- Add meaningful tags with POST /tags for discoverability
Why Use Upload Tokens for Large Files: Temporary tokens isolate upload permissions, reducing exposure if token is intercepted. They expire automatically (1-60 minutes), limiting attack surface.
Parameters:
text(string, required): Text content to upload (minimum 1 character)pId(string, required): Perspective ID to associate with uploadmetadata(object, optional): Optional metadatatitle(string): Title for the contentsource(string): Source URL or referencedescription(string): Description of content
Request Example:
curl -X POST "https://its.itscaves.com/uploads/text" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"text": "This is my important research note about quantum computing.",
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"metadata": {
"title": "Quantum Computing Notes",
"source": "https://example.com/quantum-article",
"description": "Key findings from recent quantum research"
}
}'Response (200 OK):
{
"success": true,
"ipfsTag": "/ipfs/bafkreifax7ulao52eqvlrnlbs3okawjef2gm5yvi3cntrlkaic6gpdnha",
"cid": "bafkreifax7ulao52eqvlrnlbs3okawjef2gm5yvi3cntrlkaic6gpdnha",
"size": 58,
"url": "https://itscaves.com/c//ipfs/bafkreifax7ulao52eqvlrnlbs3okawjef2gm5yvi3cntrlkaic6gpdnha",
"metadata": {
"title": "Quantum Computing Notes",
"source": "https://example.com/quantum-article",
"description": "Key findings from recent quantum research"
},
"autoTagged": true,
"tagsCreated": [
{
"parent": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"child": "uploads",
"value": 1
},
{
"parent": "uploads",
"child": "/ipfs/bafkreifax7ulao52eqvlrnlbs3okawjef2gm5yvi3cntrlkaic6gpdnha",
"value": 1
},
{
"parent": "/ipfs/bafkreifax7ulao52eqvlrnlbs3okawjef2gm5yvi3cntrlkaic6gpdnha",
"child": "text/plain",
"value": 1
}
]
}Response Fields:
success(boolean): Upload successipfsTag(string): IPFS tag (cave name) for the uploaded contentcid(string): IPFS content identifiersize(number): Content size in bytesurl(string): Caves URL to view the contentmetadata(object): The metadata providedautoTagged(boolean): Whether automatic tagging occurredtagsCreated(array): Connections automatically created
Next Steps: Use POST /tags to add meaningful tags to organize this content (e.g., topics, categories, sources).
Error Responses:
- 400 Bad Request: Missing text or pId, or text is empty
- 401 Unauthorized: Invalid API key
- 403 Forbidden: Not authorized to use this pId
- 500 Internal Server Error: Server error or IPFS upload failed
POST /oauth/upload-token
Create a short-lived upload token for large text files (>=100KB).
Authentication: Required
When to Use: Use this endpoint when uploading text content >= 100KB. The token provides temporary elevated permissions for the upload operation without exposing your primary API key.
Parameters:
pId(string, required): The perspective IDexpirationMinutes(number, optional, default: 10, range: 1-60): Token validity duration
Request Example:
curl -X POST "https://its.itscaves.com/oauth/upload-token" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"expirationMinutes": 10
}'Response (200 OK):
{
"upload_token": "temp_abc123def456...",
"expires_at": "2026-03-19T12:10:00Z",
"expires_in": 600,
"curl_example": "curl -X POST \"https://its.itscaves.com/uploads/text\" -H \"Authorization: Bearer temp_abc123def456...\" -H \"Content-Type: application/json\" -d '{\"text\":\"...\",\"pId\":\"0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0\"}'"
}Response Fields:
upload_token(string): Temporary Bearer token for uploadexpires_at(string): ISO timestamp when token expiresexpires_in(number): Seconds until expirationcurl_example(string): Ready-to-use curl command with token
Workflow:
- Call this endpoint to get upload token
- Use token immediately with POST /uploads/text
- Token expires after specified duration
Error Responses:
- 400 Bad Request: Missing pId or invalid expirationMinutes
- 401 Unauthorized: Invalid API key
- 403 Forbidden: Not authorized to use this pId
GET /tags/{ipfsTag}
Fetch content from IPFS by tag (for images or text files with proper content-type metadata).
Authentication: Required
Path Parameters:
{ipfsTag}(string, required): URL-encoded IPFS tag (e.g.,/ipfs/bafkreifax...)
Request Example:
curl -X GET "https://its.itscaves.com/tags/%2Fipfs%2Fbafkreifax7ulao52eqvlrnlbs3okawjef2gm5yvi3cntrlkaic6gpdnha" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK) - Text Content:
{
"status": "success",
"contentType": "ipfs",
"data": {
"contentType": "text/plain",
"size": 58,
"data": "This is my important research note about quantum computing."
}
}Response (200 OK) - Image Content:
{
"status": "success",
"contentType": "ipfs",
"data": {
"contentType": "image/png",
"size": 45231,
"encoding": "base64",
"data": "iVBORw0KGgoAAAANSUhEUgAA..."
}
}Response Fields:
status(string): "success" or "error"contentType(string): "ipfs"data(object): Content detailscontentType(string): MIME type (text/plain, image/png, image/jpeg)size(number): Content size in bytesencoding(string): "base64" for imagesdata(string): Content (text) or base64 (images)
Error Responses:
- 400 Bad Request: Invalid IPFS tag format
- 401 Unauthorized: Invalid API key
- 404 Not Found: IPFS content not found or no valid content-type metadata
- 500 Internal Server Error: Server error or IPFS gateway failure
Note: Content must have valid content-type metadata (image/png, image/jpeg, or text/plain) in the Caves system.
Related MCP Tool: The caves__fetch_content MCP tool automatically detects whether input is an IPFS tag or URL, calling the appropriate endpoint:
- IPFS tags (starting with '/ipfs/') → GET /tags/{ipfsTag}
- URLs (starting with 'http') → GET /search?url={url}
When using the API directly, call the appropriate endpoint based on your input type.
GET /search?url={url}
Fetch and extract text content and metadata from a URL.
Authentication: Required
Query Parameters:
url(string, required): URL-encoded URL to fetch
Request Example:
curl -X GET "https://its.itscaves.com/search?url=https%3A%2F%2Fexample.com%2Farticle" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Response (200 OK):
{
"ok": true,
"url": "https://example.com/article",
"title": "Understanding Quantum Computing",
"description": "A comprehensive guide to quantum computing principles",
"text": "Full extracted text content from the page...",
"metadata": {
"author": "Dr. Jane Smith",
"publishedDate": "2026-02-15",
"image": "https://example.com/images/quantum.jpg"
}
}Response Fields:
ok(boolean): Extraction successurl(string): The URL that was fetchedtitle(string): Page titledescription(string): Meta descriptiontext(string): Extracted text contentmetadata(object): Additional metadata found on page
Error Responses:
- 400 Bad Request: Missing or invalid URL
- 401 Unauthorized: Invalid API key
- 404 Not Found: URL not accessible
- 500 Internal Server Error: Server error or extraction failure
Related MCP Tool: The caves__fetch_content MCP tool automatically detects whether input is an IPFS tag or URL, calling the appropriate endpoint:
- IPFS tags (starting with '/ipfs/') → GET /tags/{ipfsTag}
- URLs (starting with 'http') → GET /search?url={url}
When using the API directly, call the appropriate endpoint based on your input type.
Subscription Management
Manage crypto subscriptions (detailed reference available in crypto-subscribe skill).
Multi-Step Workflow: Crypto subscriptions require calling multiple endpoints in sequence. The MCP tool caves__crypto_subscribe handles this workflow automatically, but when using the API directly, follow these steps:
Workflow Steps:
- GET /subscription/crypto/config - View available plans and supported chains/tokens
- POST /subscription/crypto/payment - Create payment session with chosen plan
- (User sends crypto transaction)
- POST /subscription/crypto/payment/{paymentId}/submit - Submit transaction hash
- GET /subscription/crypto/payment/{paymentId} - Check verification status
Implementation Tip: When building automated subscription flows, poll step 5 until status changes to 'completed' or 'failed'. Blockchain confirmation typically takes 1-5 minutes.
GET /subscription/crypto/config
Get current subscription pricing and configuration.
Authentication: Not required (public endpoint)
Request Example:
curl -X GET "https://its.itscaves.com/subscription/crypto/config" \
-H "Content-Type: application/json"Response (200 OK):
{
"plans": {
"1": { "months": 1, "priceUSD": 5 },
"3": { "months": 3, "priceUSD": 12 },
"6": { "months": 6, "priceUSD": 20 },
"12": { "months": 12, "priceUSD": 35 }
},
"supportedChains": ["ethereum", "solana"],
"supportedTokens": {
"ethereum": ["ETH", "USDC"],
"solana": ["SOL", "USDC"]
}
}POST /subscription/crypto/payment
Create a crypto payment session.
Authentication: Required
Parameters:
months(number, required): Subscription duration (1, 3, 6, or 12)chain(string, required): Blockchain ("ethereum" or "solana")token(string, required): Token to use ("ETH", "USDC", "SOL")
Request Example:
curl -X POST "https://its.itscaves.com/subscription/crypto/payment" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"months": 3,
"chain": "ethereum",
"token": "USDC"
}'Response: See crypto-subscribe skill for detailed response format.
POST /subscription/crypto/payment/{paymentId}/submit
Submit transaction hash for verification.
Authentication: Required
Path Parameters:
{paymentId}(string, required): Payment session ID
Parameters:
txHash(string, required): Blockchain transaction hash
Request Example:
curl -X POST "https://its.itscaves.com/subscription/crypto/payment/pay_abc123/submit" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json" \
-d '{
"txHash": "0x1234567890abcdef..."
}'GET /subscription/crypto/payment/{paymentId}
Check payment status.
Authentication: Required
Path Parameters:
{paymentId}(string, required): Payment session ID
Request Example:
curl -X GET "https://its.itscaves.com/subscription/crypto/payment/pay_abc123" \
-H "Authorization: Bearer cav_abc123..." \
-H "Content-Type: application/json"Note: For complete subscription workflow documentation, use the crypto-subscribe skill.
Error Handling
Common HTTP Status Codes
- 200 OK: Request successful
- 400 Bad Request: Invalid parameters or malformed request
- 401 Unauthorized: Invalid or missing API key
- 403 Forbidden: Not authorized to perform this action
- 404 Not Found: Resource doesn't exist
- 409 Conflict: Resource already exists (e.g., username taken)
- 429 Too Many Requests: Rate limit exceeded
- 500 Internal Server Error: Server-side error
- 503 Service Unavailable: Server temporarily unavailable
Error Response Format
All error responses follow this format:
{
"ok": false,
"error": "Descriptive error message",
"code": "ERROR_CODE",
"details": {
"additionalInfo": "..."
}
}Troubleshooting Common Errors
401 Unauthorized - "Invalid API key"
- Check API key format (must start with cav_)
- Verify key is active (not revoked)
- Ensure proper header format
- Regenerate key at https://itscaves.com/account403 Forbidden - "Not authorized to use this pId"
- Verify pId belongs to your account
- Check pId is correctly formatted (Ethereum address)
- Use GET /user/pIds to see your available perspectives429 Too Many Requests - "Rate limit exceeded"
- Implement exponential backoff
- Reduce request frequency
- Use batch operations when possible
- Contact support for rate limit increase500 Internal Server Error
- Check Caves status page: https://itscaves.com/status
- Retry with exponential backoff
- If persistent, contact support@itscaves.comRate Limiting & Best Practices
Rate Limits
- General endpoints: 100 requests per minute per API key
- Search endpoints: 30 requests per minute (computationally intensive)
- Connection creation: Limited by fire balance (currency consumption)
Best Practices:
- Implement exponential backoff for retries
- Cache results when appropriate
- Use batch operations (POST /tags for multiple connections)
- Monitor response headers for rate limit info
Batch Operations
Use batch operations for efficiency:
# GOOD: Create 10 connections in one request
curl -X POST "https://its.itscaves.com/tags" \
-d '{
"pId": "0x...",
"connections": [
{"parent": "a", "child": "b", "value": true},
{"parent": "a", "child": "c", "value": true},
...10 connections...
]
}'
# BAD: Create 10 connections with 10 separate requests
# (slower, wastes rate limit, inefficient)Retry Logic
Implement exponential backoff for transient errors:
async function makeRequest(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
// Success - return response
if (response.ok) return response;
// Don't retry client errors (4xx)
if (response.status >= 400 && response.status < 500) {
throw new Error(`Client error: ${response.status}`);
}
// Retry server errors (5xx) with backoff
if (i < maxRetries - 1) {
await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
continue;
}
throw new Error(`Server error: ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}Security Recommendations
Environment Variables:
# .env file
CAVES_API_KEY=cav_abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567890abcd
CAVES_API_URL=https://its.itscaves.com
# .gitignore
.env
*.env.localNever Commit API Keys:
# Add to .gitignore
.env
.env.local
config/secrets.json
api-keys.txtUse Password Managers:
- Store API keys in 1Password, LastPass, etc.
- Share with team members securely
- Enable 2FA on Caves account
Rotate Keys Regularly:
- Generate new keys quarterly
- Revoke old keys immediately
- Update all services using the key
Code Examples
JavaScript/Node.js
const CAVES_API_URL = 'https://its.itscaves.com';
const CAVES_API_KEY = process.env.CAVES_API_KEY;
// Helper function for authenticated requests
async function cavesAPI(endpoint, options = {}) {
const response = await fetch(`${CAVES_API_URL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${CAVES_API_KEY}`,
'Content-Type': 'application/json',
...options.headers,
},
});
if (!response.ok) {
throw new Error(`Caves API error: ${response.status}`);
}
return response.json();
}
// Get perspectives
const perspectives = await cavesAPI('/user/pIds');
console.log('My perspectives:', perspectives.pIds);
// Search for caves
const results = await cavesAPI('/search?s=javascript');
console.log('Search results:', results);
// Create connections
const data = await cavesAPI('/tags', {
method: 'POST',
body: JSON.stringify({
pId: '0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0',
connections: [
{ parent: 'programming', child: 'javascript', value: true },
{ parent: 'javascript', child: 'typescript', value: true },
],
}),
});
console.log('Created connections:', data);Python
import os
import requests
CAVES_API_URL = 'https://its.itscaves.com'
CAVES_API_KEY = os.getenv('CAVES_API_KEY')
# Helper function for authenticated requests
def caves_api(endpoint, method='GET', data=None):
headers = {
'Authorization': f'Bearer {CAVES_API_KEY}',
'Content-Type': 'application/json',
}
url = f'{CAVES_API_URL}{endpoint}'
if method == 'GET':
response = requests.get(url, headers=headers)
elif method == 'POST':
response = requests.post(url, headers=headers, json=data)
elif method == 'DELETE':
response = requests.delete(url, headers=headers, json=data)
response.raise_for_status()
return response.json()
# Get perspectives
perspectives = caves_api('/user/pIds')
print('My perspectives:', perspectives['pIds'])
# Search for caves
results = caves_api('/search?s=python')
print('Search results:', results)
# Create connections
data = caves_api('/tags', method='POST', data={
'pId': '0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0',
'connections': [
{'parent': 'programming', 'child': 'python', 'value': True},
{'parent': 'python', 'child': 'django', 'value': True},
],
})
print('Created connections:', data)cURL Script Example
#!/bin/bash
# Load API key from environment
CAVES_API_KEY="${CAVES_API_KEY:-}"
if [ -z "$CAVES_API_KEY" ]; then
echo "Error: CAVES_API_KEY environment variable not set"
exit 1
fi
# Base URL
API_URL="https://its.itscaves.com"
# Get perspectives
echo "Fetching perspectives..."
curl -s "$API_URL/user/pIds" \
-H "Authorization: Bearer $CAVES_API_KEY" \
-H "Content-Type: application/json" \
| jq .
# Search caves
echo "Searching for 'javascript'..."
curl -s "$API_URL/search?s=javascript" \
-H "Authorization: Bearer $CAVES_API_KEY" \
-H "Content-Type: application/json" \
| jq .
# Create connections
echo "Creating connections..."
curl -s -X POST "$API_URL/tags" \
-H "Authorization: Bearer $CAVES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pId": "0xE1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0",
"connections": [
{"parent": "programming", "child": "javascript", "value": true}
]
}' \
| jq .When to Use MCP vs Direct API
Use MCP Tools (Preferred for Claude)
Advantages:
- OAuth authentication (more secure)
- Built-in tool abstractions
- Automatic error handling
- Seamless Claude Code integration
- No API key management
Use cases:
- Working in Claude Desktop or Claude Code
- Interactive knowledge graph building
- Quick exploration and testing
- No custom integration needed
Use Direct HTTP API
Advantages:
- Works outside Claude ecosystem
- Full control over requests
- Can be used in any programming language
- Suitable for automation/scripting
- Integration with external systems
Use cases:
- Building custom applications
- Creating scripts and automation
- Integrating with non-Claude systems
- Server-side applications
- Batch processing workflows
Additional Resources
- Caves Homepage: https://itscaves.com
- Account Management: https://itscaves.com/account
- API Status: https://itscaves.com/status
- Support: support@itscaves.com
- Discord Community: https://discord.com/invite/8bW2xwv7kc
- GitHub Plugin: https://github.com/ic-caves/caves-claude-plugin
- Documentation: https://github.com/ic-caves/caves-docs
Version & Updates
API Version: v1 (stable) Last Updated: 2026-03-19 Skill Version: 0.6.0
This reference documents the current production API. For the latest updates and changes, visit the Caves documentation or join the Discord community.
Summary
This API reference provides complete HTTP access to the Caves knowledge graph system. Key features:
- ✅ REST API with JSON responses
- ✅ API key authentication (two header formats)
- ✅ Comprehensive endpoint coverage (11 core endpoints)
- ✅ Batch operations support
- ✅ IPFS content management
- ✅ URL content extraction
- ✅ Perspective management
- ✅ Knowledge graph operations
- ✅ Discovery & search capabilities
For quick starts and interactive use, prefer MCP tools. For custom integrations and automation, use this HTTP API reference.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

