{"openapi":"3.0.3","info":{"title":"AlpacaBase Management API","version":"1.4.0","description":"Manage AlpacaBase projects, databases, auth, storage, and edge functions.\n\nAuthenticate with: Authorization: Bearer <token>\n\nGet a token: POST /auth/login → use the token → or POST /tokens to create a PAT.\n\nQuick start:\n1. POST /auth/login to get a token\n2. POST /projects to create a project (backend_type: shared = instant)\n3. Poll GET /projects/:id/status until status is healthy\n4. Use postgrest_url from the project for your database REST API","contact":{"url":"https://alpaca-cloud.com"}},"servers":[{"url":"https://app.alpaca-cloud.com","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Personal Access Token or user JWT. Get via POST /auth/login or GET /tokens"}}},"paths":{"/health":{"get":{"tags":["System"],"summary":"Health check","security":[],"responses":{"200":{"description":"{ok:true}"}}}},"/projects/{id}/mcp":{"get":{"tags":["MCP"],"summary":"MCP server info","description":"Get Model Context Protocol endpoint info and Claude Desktop config for this project.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"Project ID"}],"responses":{"200":{"description":"MCP endpoint details and Claude config"}}},"post":{"tags":["MCP"],"summary":"MCP JSON-RPC endpoint","description":"Model Context Protocol endpoint. Send JSON-RPC 2.0 messages. Auth: apikey header (service_role key). Tools: run_sql, list_tables, get_table_schema, list_auth_users, create_auth_user, delete_auth_user, get_project_info.","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","example":"2.0"},"id":{"type":"integer","example":1},"method":{"type":"string","enum":["initialize","tools/list","tools/call","ping"],"example":"tools/list"},"params":{"type":"object"}},"required":["jsonrpc","method"]}}}},"responses":{"200":{"description":"JSON-RPC response"}}}},"/openapi.json":{"get":{"tags":["System"],"summary":"This OpenAPI spec","security":[],"responses":{"200":{"description":"OpenAPI 3.0 JSON"}}}},"/regions":{"get":{"tags":["Discovery"],"summary":"List valid region IDs","description":"Valid values: eu-central, eu-west, eu-north, us-east, us-west, ap-south","security":[],"responses":{"200":{"description":"Region list with names and datacenter locations"}}}},"/plans":{"get":{"tags":["Discovery"],"summary":"List plans with pricing and server specs","security":[],"responses":{"200":{"description":"Plan list"}}}},"/backend-types":{"get":{"tags":["Discovery"],"summary":"List backend types with provisioning times","description":"shared=instant, dedicated=3-6min VM, frontend=static hosting","security":[],"responses":{"200":{"description":"Backend type descriptions"}}}},"/auth/register":{"post":{"tags":["Auth"],"summary":"Create account","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8},"full_name":{"type":"string"}}}}}},"responses":{"201":{"description":"User created + JWT token"}}}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Login and get JWT","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"{token:...,user:{...}}"}}}},"/auth/me":{"get":{"tags":["Auth"],"summary":"Get current user","responses":{"200":{"description":"User profile"}}}},"/tokens":{"get":{"tags":["Auth"],"summary":"List personal access tokens","responses":{"200":{"description":"Token list"}}},"post":{"tags":["Auth"],"summary":"Create a PAT","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"New PAT (shown once)"}}}},"/projects":{"get":{"tags":["Projects"],"summary":"List your projects","responses":{"200":{"description":"Array of project objects"}}},"post":{"tags":["Projects"],"summary":"Create a project","description":"Creates a new AlpacaBase project.\n\n- backend_type=shared: provisioned in ~2 seconds on shared cluster\n- backend_type=dedicated: private Hetzner VM, takes 3-6 minutes. Poll /projects/:id/status.\n- backend_type=frontend: static site hosting, no database\n\nValid regions: eu-central, eu-west, eu-north, us-east, us-west, ap-south\nValid plans: free, starter, pro, team, enterprise","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{2,29}$","description":"3-30 chars, lowercase letters, numbers, hyphens only"},"region":{"type":"string","enum":["eu-central","eu-west","eu-north","us-east","us-west","ap-south"],"default":"eu-central"},"plan":{"type":"string","enum":["free","starter","pro","team","enterprise"],"default":"free"},"backend_type":{"type":"string","enum":["shared","dedicated","frontend","app"],"default":"shared","description":"shared=instant; dedicated=private VM 3-6 min; frontend=static site; app=Docker container (deploy via /compute/deploy)"}}}}}},"responses":{"201":{"description":"Project object. If dedicated, poll /projects/:id/status until status=healthy"}}}},"/projects/{id}":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Project ID from GET /projects"}],"get":{"tags":["Projects"],"summary":"Get project details","responses":{"200":{"description":"Full project object with db_url, api keys, etc."}}},"patch":{"tags":["Projects"],"summary":"Update project settings","description":"Update: repo_url, build_command, output_dir, install_command, production_branch, env_vars, email_notifications, slack_webhook, forms_enabled, webhook_secret","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"repo_url":{"type":"string"},"build_command":{"type":"string","default":"npm run build"},"output_dir":{"type":"string","default":"dist"},"install_command":{"type":"string","default":"npm install"},"production_branch":{"type":"string","default":"main"},"env_vars":{"oneOf":[{"type":"object","additionalProperties":{"type":"string"},"description":"Plain object: {KEY: value}"},{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}},"description":"Array format: [{key, value}] — also accepted"}],"description":"Environment variables as {KEY: value} object (preferred) or [{key, value}] array. Both are accepted."},"email_notifications":{"type":"boolean"},"slack_webhook":{"type":"string","nullable":true},"forms_enabled":{"type":"boolean"},"github_token":{"type":"string","nullable":true,"description":"GitHub Personal Access Token (PAT) with `repo` scope. Required to deploy private repositories. Stored encrypted. Set to null to remove. Never returned in API responses — only `has_github_token: true/false` is exposed."}}}}}},"responses":{"200":{"description":"Updated fields"},"400":{"description":"No updatable fields or invalid request"}}},"delete":{"tags":["Projects"],"summary":"Delete project and all resources","responses":{"200":{"description":"{ok:true}"}}}},"/projects/{id}/status":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"get":{"tags":["Projects"],"summary":"Poll provisioning status + service health","description":"Returns status (provisioning|healthy|error) and per-service health.\n\nFor **dedicated** projects, probes each service and returns:\n- services.database (PostgREST)\n- services.auth (alpaca-auth)\n- services.storage (alpaca-storage)\n- services.realtime\n\nFor **shared** projects, returns availability flags (storage: not available on shared).\n\nFor **frontend**, returns hosting status only.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"{ status, services: { auth: { up, status, endpoint }, ... } }"}}}},"/projects/{id}/reprovision":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"post":{"tags":["Projects"],"summary":"Retry provisioning (dedicated, errored only)","description":"Re-creates the VM for a dedicated project that failed provisioning. Only works if no VM exists yet. For live projects, use /services/:service/restart instead.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"{ ok: true, server_type, location }"},"400":{"description":"Already has a running server, or not a dedicated project"}}}},"/projects/{id}/query":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"post":{"tags":["Database"],"summary":"Execute raw SQL","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sql"],"properties":{"sql":{"type":"string","example":"SELECT * FROM users LIMIT 10"}}}}}},"responses":{"200":{"description":"Query results"}}}},"/projects/{id}/functions":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"get":{"tags":["Functions"],"summary":"List edge functions"},"post":{"tags":["Functions"],"summary":"Create edge function","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","code"],"properties":{"name":{"type":"string"},"code":{"type":"string","description":"JavaScript/TypeScript function code"}}}}}}}},"/projects/{id}/functions/{funcId}/deploy":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"in":"path","name":"funcId","required":true,"schema":{"type":"integer"}}],"post":{"tags":["Functions"],"summary":"Deploy an edge function","responses":{"200":{"description":"Deployment status"}}}},"/projects/{id}/deploy":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"post":{"tags":["Frontend Hosting"],"summary":"Trigger a frontend build/deploy","description":"Triggers a build and deploy for a frontend project.\n\n**Repository access:**\n- **Public repos**: work out of the box — just set `repo_url` via PATCH /projects/:id\n- **Private repos**: require a `github_token` (GitHub PAT with `repo` scope) set via PATCH /projects/:id. Without it, the clone step will fail with a 128 exit code (auth error). Set it once and it persists across deploys.\n\n**Two ways to call:**\n1. **Authenticated**: `Authorization: Bearer <token>` header\n2. **GitHub webhook**: `POST /projects/:id/deploy?token=<webhook_secret>` — configure this URL in your GitHub repo Settings → Webhooks → Payload URL\n\nGet your `webhook_secret` and `webhook_url` from GET /projects/:id.\n\n**Build flow:** clone → install (`install_command`) → build (`build_command`) → deploy `output_dir` to static hosting.\n\n**Track progress:** Poll GET /projects/:id/status — `provision_message` shows current step (Cloning, Installing, Building, Deployed).","security":[],"parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string"},"description":"Webhook secret for unauthenticated GitHub webhook calls"}],"responses":{"200":{"description":"{ ok: true, message: \"Build triggered\" }"},"400":{"description":"Not a frontend project or no repo_url set"},"401":{"description":"Unauthorized"}}}},"/projects/{id}/build-logs":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"get":{"tags":["Frontend Hosting"],"summary":"Get full build log for a frontend project","description":"Returns the full stderr/stdout from the last failed build. The `provision_message` field on the project is limited to 500 chars; this endpoint returns the complete output.\n\nFor successful builds, `has_logs` will be false (logs are cleared on success).\n\nPoll this endpoint after triggering a deploy to see live build progress.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"{ has_logs: bool, raw: string, sections: [{section, content}] }"},"404":{"description":"Project not found"}}}},"/projects/{id}/deploy-key":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"post":{"tags":["Frontend Hosting"],"summary":"Generate an SSH deploy key for private repos (alternative to github_token)","description":"Generates an SSH key pair for this project. Returns the public key to add to your GitHub repo under Settings → Deploy Keys. The private key is stored server-side and used automatically during clones.\n\nUse this as an alternative to `github_token` when you prefer not to store a PAT. Only one deploy key is active per project at a time.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"{ public_key: \"ssh-ed25519 AAAA...\", fingerprint: \"SHA256:...\", note: \"Add this public key to your repo deploy keys\" }"},"400":{"description":"Not a frontend project"}}}},"/projects/{id}/services":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"get":{"tags":["Services"],"summary":"List service statuses (dedicated only)","description":"Returns systemd status for all services on a dedicated project VM: auth, postgrest, storage, realtime, nginx, postgres, pgbouncer.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"{ services: { auth: { status, unit }, ... } }"}}}},"/projects/{id}/services/{service}/restart":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"in":"path","name":"service","required":true,"schema":{"type":"string","enum":["auth","postgrest","storage","realtime","nginx"]}}],"post":{"tags":["Services"],"summary":"Restart a service on the VM (dedicated only)","description":"Restarts a named systemd service on the project VM via SSH.\n\nUse this when a service returns 502 (e.g. auth, storage). Valid services: auth, postgrest, storage, realtime, nginx.\n\n**Dedicated projects only.**","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"{ ok: true, service, systemd_unit, status }"},"400":{"description":"Invalid service name or not a dedicated project"},"500":{"description":"SSH failed or restart failed"}}}},"x-service-availability":{"description":"## Service availability by backend_type\n\n| Service | shared | dedicated | frontend |\n|---------|--------|-----------|----------|\n| Database (PostgREST /rest/v1/) | ✅ | ✅ | ❌ |\n| Auth (/auth/v1/) | ✅ | ✅ | ❌ |\n| Storage (/storage/v1/) | ❌ | ✅ | ❌ |\n| Realtime WebSocket (/realtime/v1/) | ✅ | ✅ | ❌ |\n| Edge Functions (/functions/v1/) | ❌ | ✅ | ❌ |\n| Static Hosting | ❌ | ❌ | ✅ |\n\n### Auth endpoint reference (Supabase-compatible)\nConfigure your Supabase JS client with:\n```js\ncreateClient(auth_url.replace('/auth/v1', ''), anon_key)\n// or directly:\ncreateClient(\"https://your-project.alpaca-cloud.com\", anon_key)\n```\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| /auth/v1/signup | POST | Register with email+password |\n| /auth/v1/token?grant_type=password | POST | Sign in, get access_token + refresh_token |\n| /auth/v1/token?grant_type=refresh_token | POST | Refresh access token |\n| /auth/v1/user | GET | Get current user (Bearer token) |\n| /auth/v1/user | PUT | Update email, password, user_metadata |\n| /auth/v1/logout | POST | Invalidate session |\n| /auth/v1/admin/users | GET | List all users (service_role only) |\n| /auth/v1/admin/users/:id | DELETE | Delete a user (service_role only) |\n\n### auth.uid() in PostgREST / RLS\nWhen using a valid auth JWT, `auth.uid()` returns the user's UUID.\nUse in RLS policies: `auth.uid() = user_id`"}}}