Claw Protocol Specification
Version 0.1 · Draft · March 2026
Author: ClawDrop
1. Introduction
The Claw Protocol defines a standard interface for programmatic file exchange. It is designed for AI agents, CLI tools, and automated systems that need to upload, retrieve, inspect, and delete files via simple HTTP operations.
Claw maps directly onto HTTP. Every Claw operation is a single HTTP request. Any HTTP client can speak Claw without specialized libraries.
1.1 Design Principles
- One operation, one request. No multi-step flows, no sessions, no state machines.
- HTTP is the transport. Claw is an application-layer convention over standard HTTP methods and headers.
- Programmatic first. The primary interface is CLI and code, not browsers. Browser rendering is content negotiation, not a separate product.
- No accounts. Identity is an API key. There are no usernames, passwords, profiles, or sessions.
- Ephemeral by default. Files expire unless explicitly made permanent by an authenticated client.
1.2 Terminology
| Term | Definition |
|---|---|
| Registry | A Claw-compatible server (e.g., clawdrop.io) |
| Slug | A short, unique identifier for an uploaded file |
| Namespace | An optional @name prefix for organizing files under an API key |
| Drop | The act of uploading a file to a registry |
| Fetch | The act of downloading a file from a registry |
2. URI Scheme
Claw defines the claw:// URI scheme as syntactic sugar over HTTPS:
claw://<slug> → https://<registry>/<slug> claw://<slug>?raw → https://<registry>/<slug>?raw claw://<slug>?m → https://<registry>/<slug>?m claw://sha256:<hash> → https://<registry>/sha256/<hash> claw://@<namespace>/<name> → https://<registry>/@<namespace>/<name>
The default registry is clawdrop.io. Clients MAY configure an alternative registry.
3. Operations
3.1 Drop (Upload)
Upload a file to the registry.
POST / Content-Type: multipart/form-data Form field: file (required)
Request Headers
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Must be multipart/form-data |
X-API-Key | No | API key for authenticated uploads |
Max-Days | No | Expiration in days (1–90, default 7). permanent with API key. |
Accept | No | application/json for structured response |
X-Content-Address | No | true to enable content-addressable mode |
X-Slug | No | Custom slug (requires API key, 3–64 chars, alphanumeric + hyphens) |
X-Namespace | No | Namespace prefix (requires API key) |
Response (text/plain, default)
https://registry/slug\n
Response (application/json)
{
"url": "https://registry/slug",
"slug": "a3Fk82xQ",
"expires_at": "2026-03-16T00:00:00.000Z",
"size_bytes": 45231,
"content_type": "application/pdf",
"sha256_hash": "abc123..."
}
Status Codes
| Code | Meaning |
|---|---|
| 200 | Upload successful |
| 400 | Missing file, empty file, or invalid parameters |
| 409 | Custom slug already taken |
| 413 | File exceeds size limit |
| 429 | Rate limit exceeded |
| 451 | Content blocked |
| 502 | Storage unavailable |
3.2 Fetch (Download)
Retrieve a file from the registry.
GET /<slug> GET /<slug>?raw GET /@<namespace>/<slug> GET /sha256/<hash>
Content Negotiation
Accept: text/html(browsers): Returns an HTML preview page with metadata, file preview, download link, and OG meta tags.- All other clients (curl, wget, programmatic): Returns the raw file bytes.
?rawquery parameter: Always returns raw file bytes regardless of Accept header.
Response Headers
| Header | Description |
|---|---|
Content-Type | MIME type of the file |
Content-Length | File size in bytes |
Content-Disposition | inline or attachment (dangerous types forced to attachment) |
ETag | SHA-256 hash of content |
Cache-Control | public, max-age=86400 |
Status Codes
| Code | Meaning |
|---|---|
| 200 | File served |
| 301 | Redirect (content-addressable lookups) |
| 404 | File not found |
| 410 | File expired |
3.3 Inspect (Metadata)
Retrieve metadata about a file without downloading it.
GET /<slug>?m
Response
{
"slug": "a3Fk82xQ",
"filename": "report.pdf",
"content_type": "application/pdf",
"size_bytes": 45231,
"sha256_hash": "abc123...",
"expires_at": "2026-03-16T00:00:00.000Z",
"created_at": "2026-03-09T00:00:00.000Z",
"permanent": false
}
3.4 Delete
Remove a file. Requires the same API key used to upload it.
DELETE /<slug> X-API-Key: claw_...
Status Codes
| Code | Meaning |
|---|---|
| 204 | Deleted |
| 401 | Missing or invalid API key |
| 403 | API key does not match upload owner |
| 404 | File not found |
4. Authentication
4.1 API Keys
API keys are the sole authentication mechanism. There are no usernames, passwords, or OAuth flows.
Key Generation
POST /keys
Returns a new API key exactly once. The server stores only the SHA-256 hash.
Key Format: claw_ prefix + 32 cryptographically random base62 characters.
Example: claw_a7Kx9mP2rN4wQ8bF3vT6yJ1hD5sL0gC
Key Usage: Pass via the X-API-Key header on any request.
4.2 Key Introspection
GET /keys/me X-API-Key: claw_...
Returns upload history and usage statistics for the authenticated key.
{
"uploads": [
{"slug": "a3Fk82xQ", "filename": "report.pdf", "created_at": "...", "expires_at": "..."}
],
"usage": {
"upload_count": 47,
"bytes_stored": 125829120,
"bytes_served": 524288000
},
"namespace": "@myproject"
}
5. Rate Limiting
Rate limits are communicated via standard headers on every response:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining in current window |
Retry-After | Seconds to wait (only on 429 responses) |
Default Limits
| Tier | Limit |
|---|---|
| Free (anonymous) | 60 requests/hour |
| Pro | 600 requests/hour |
| Studio | 6,000 requests/hour |
6. Content-Addressable Mode
When X-Content-Address: true is sent with an upload:
- The server computes the SHA-256 hash of the content.
- If a file with that hash already exists and has not expired, the server returns the existing URL (HTTP 200, not 201).
- If no match exists, normal upload proceeds and a
content:{hash}index is stored.
Lookup by Hash
GET /sha256/<hash>
Returns HTTP 301 redirect to the canonical slug URL. This enables deduplication and convergent file references across independent agents.
7. Namespaces
Namespaces provide URL grouping under an API key.
Claiming a namespace: Send X-Namespace: myproject on any upload with an API key. The namespace is claimed on first use and bound to that API key.
Namespace URLs: https://registry/@myproject/filename
Rules
- One namespace per API key.
- Namespace names: 2–32 characters, lowercase alphanumeric + hyphens, must start with a letter.
- Namespace ownership is verified on every upload to that namespace.
8. Permanence
By default, all files are ephemeral with a 7-day TTL (free tier).
To create a permanent file, send Max-Days: permanent with a valid API key on a Pro or Studio tier.
Permanent files:
- Have no expiration
- Are stored indefinitely while the subscription is active
- Require an API key (anonymous uploads are always ephemeral)
- Are the foundation for load-bearing URLs in documentation, configs, and agent memory
9. Error Codes
All errors return JSON:
{
"error": "Human-readable message",
"retry_after": 3600
}
| HTTP Status | Claw Meaning |
|---|---|
| 400 | Bad request (missing file, invalid parameters) |
| 401 | Authentication required |
| 403 | Forbidden (wrong API key for resource) |
| 404 | Resource not found |
| 409 | Conflict (slug taken) |
| 410 | Gone (file expired) |
| 413 | Payload too large |
| 429 | Rate limit exceeded |
| 451 | Content blocked |
| 500 | Internal server error |
| 502 | Storage unavailable |
10. Conformance
A Claw-compatible server MUST implement:
POST /file upload with multipart/form-dataGET /<slug>file retrieval- Content-Type preservation
- Expiration semantics (files MUST eventually expire unless permanent)
- SHA-256 content hashing
- Rate limiting headers
A Claw-compatible server SHOULD implement:
- API key authentication (
POST /keys,X-API-Keyheader) - Content negotiation (browser vs programmatic)
- Content-addressable mode
- Namespaces
- The
?mmetadata endpoint - The
?rawbypass
Appendix A: Quick Reference
# Upload a file $ curl -F "[email protected]" https://clawdrop.io # Upload with API key and custom expiration $ curl -F "[email protected]" -H "X-API-Key: claw_..." -H "Max-Days: 30" https://clawdrop.io # Upload permanent file $ curl -F "[email protected]" -H "X-API-Key: claw_..." -H "Max-Days: permanent" https://clawdrop.io # Get JSON response $ curl -F "[email protected]" -H "Accept: application/json" https://clawdrop.io # Download a file $ curl https://clawdrop.io/a3Fk82xQ -o report.pdf # Inspect metadata $ curl https://clawdrop.io/a3Fk82xQ?m # Delete a file $ curl -X DELETE -H "X-API-Key: claw_..." https://clawdrop.io/a3Fk82xQ # Generate API key $ curl -X POST https://clawdrop.io/keys # Check usage $ curl -H "X-API-Key: claw_..." https://clawdrop.io/keys/me # Content-addressable upload $ curl -F "[email protected]" -H "X-Content-Address: true" https://clawdrop.io # Custom slug $ curl -F "[email protected]" -H "X-API-Key: claw_..." -H "X-Slug: brand-logo" https://clawdrop.io # Namespaced upload $ curl -F "[email protected]" -H "X-API-Key: claw_..." -H "X-Namespace: myproject" https://clawdrop.io
The Claw Protocol is open. This spec is public. Fork it if we disappear.