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_xxxxxxxxxxxxxxxxxxxxxxxx

Auth

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 email
  • customer.subscription.updated — status sync + cancellation email
  • customer.subscription.deleted — downgrade to free
  • invoice.payment_succeeded — payment confirmation email
  • invoice.payment_failed — past due status + alert email

Error format

All errors return:

{
  "error": {
    "code": "WORKSPACE_NOT_FOUND",
    "message": "Workspace not found",
    "status": 404
  }
}
CodeStatusMeaning
INVALID_REQUEST400Malformed request body
UNAUTHORIZED401Missing or invalid auth
FORBIDDEN403Insufficient permissions
NOT_FOUND404Resource not found
CONFLICT409Resource already exists
RATE_LIMITED429Too many requests
INTERNAL_ERROR500Server error

Rate limits

PlanRequests/minRequests/day
Free601,000
Cloud30050,000

Response headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1707500000