API Reference
The ClawKeep Cloud REST API. Base URL: https://api.clawkeep.com
Authentication
All protected endpoints require one of:
# JWT (web dashboard) — 15-minute access token
Authorization: Bearer eyJhbG...
# API key (CLI) — never expires, revoke from dashboard
Authorization: Bearer ck_live_xxxxxxxxxxxxxxxxxxxxxxxxAuth
POST /api/auth/register
Create a new account.
// Request
{
"email": "user@example.com",
"password": "securepassword123"
}
// Response 201
{
"user": {
"id": "usr_01h5x3kj7p...",
"email": "user@example.com",
"plan": "free"
},
"access_token": "eyJhbG...",
"expires_in": 900
}POST /api/auth/login
Authenticate and get tokens.
// Request
{ "email": "user@example.com", "password": "..." }
// Response 200
{
"user": { ... },
"access_token": "eyJhbG...",
"expires_in": 900
}The refresh_token is set as an httpOnly cookie. Access tokens expire in 15 minutes and are auto-refreshed by the frontend.
POST /api/auth/refresh
Get a new access token using the refresh cookie.
// Response 200
{ "access_token": "eyJhbG...", "expires_in": 900 }POST /api/auth/logout
Invalidate the refresh token.
User
GET /api/user
Get the current user profile.
// Response 200
{
"user": {
"id": "usr_01h5x3kj7p...",
"email": "user@example.com",
"plan": "cloud",
"storage_used_bytes": 1073741824,
"storage_limit_bytes": 107374182400,
"workspace_count": 3
}
}PATCH /api/user
Update email or password.
// Request
{ "email": "newemail@example.com" }DELETE /api/user
Delete account and all data. Irreversible.
// Request
{ "confirm": "DELETE MY ACCOUNT" }Workspaces
GET /api/workspaces
List all workspaces.
// Response 200
{
"workspaces": [
{
"id": "ws_01jkxyz...",
"name": "my-project",
"storage_bytes": 50331648,
"chunk_count": 45,
"last_sync_at": "2026-02-09T18:00:00Z"
}
]
}POST /api/workspaces
Create a workspace.
// Request
{ "name": "my-project" }
// Response 201
{ "workspace": { "id": "ws_01jkxyz...", "name": "my-project", ... } }GET /api/workspaces/:id
Get workspace details.
DELETE /api/workspaces/:id
Delete workspace. Must confirm with workspace name.
// Request
{ "confirm": "my-project" }GET /api/workspaces/:id/credentials
Get scoped S3 credentials for direct R2 access. Credentials expire after 24 hours. The CLI uses these to upload/download directly to Cloudflare R2 — data never passes through the API.
// Response 200
{
"credentials": {
"endpoint": "https://xxxx.r2.cloudflarestorage.com",
"bucket": "clawkeep-prod",
"prefix": "workspaces/ws_01jkxyz.../",
"access_key_id": "...",
"secret_access_key": "...",
"region": "auto"
},
"expires_at": "2026-02-10T18:00:00Z"
}GET /api/workspaces/:id/stats?period=30d
Usage statistics for a workspace.
// Response 200
{
"stats": {
"period": "30d",
"storage_bytes_current": 50331648,
"sync_count": 156,
"daily": [
{ "date": "2026-02-09", "storage_bytes": 50331648, "syncs": 5 }
]
}
}API Keys
GET /api/keys
List API keys. The full secret is never returned after creation.
// Response 200
{
"keys": [
{
"id": "key_01h5...",
"name": "My MacBook",
"prefix": "ck_live_abc...",
"last_used_at": "2026-02-09T18:00:00Z"
}
]
}POST /api/keys
Create a new API key. The secret is shown only once.
// Request
{ "name": "My MacBook" }
// Response 201
{
"key": {
"id": "key_01h5...",
"name": "My MacBook",
"secret": "ck_live_xxxxxxxxxxxxxxxxxxxxxxxx"
},
"warning": "Save this key now. It won't be shown again."
}DELETE /api/keys/:id
Revoke an API key. Takes effect immediately.
Billing
GET /api/billing
Current billing status and usage.
POST /api/billing/checkout
Create a Stripe checkout session to upgrade.
// Request
{
"plan": "cloud",
"success_url": "https://clawkeep.com/dashboard?upgraded=true",
"cancel_url": "https://clawkeep.com/dashboard/billing"
}
// Response 200
{ "checkout_url": "https://checkout.stripe.com/..." }POST /api/billing/portal
Get Stripe customer portal URL for subscription management.
Webhooks
POST /api/webhooks/stripe
Receives Stripe events. Handles:
checkout.session.completed— plan upgrade + welcome emailcustomer.subscription.updated— status sync + cancellation emailcustomer.subscription.deleted— downgrade to freeinvoice.payment_succeeded— payment confirmation emailinvoice.payment_failed— past due status + alert email
Error format
All errors return:
{
"error": {
"code": "WORKSPACE_NOT_FOUND",
"message": "Workspace not found",
"status": 404
}
}| Code | Status | Meaning |
|---|---|---|
INVALID_REQUEST | 400 | Malformed request body |
UNAUTHORIZED | 401 | Missing or invalid auth |
FORBIDDEN | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource not found |
CONFLICT | 409 | Resource already exists |
RATE_LIMITED | 429 | Too many requests |
INTERNAL_ERROR | 500 | Server error |
Rate limits
| Plan | Requests/min | Requests/day |
|---|---|---|
| Free | 60 | 1,000 |
| Cloud | 300 | 50,000 |
Response headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1707500000