{"components":{"securitySchemes":{"bearer":{"scheme":"bearer","type":"http"},"cookie":{"in":"cookie","name":"msaas_session","type":"apiKey"}}},"info":{"description":"Every credential (API key, access token, session, sandbox token) has its own token bucket; when it is empty the API answers 429 {\"error\",\"code\":\"rate_limited\"} with a Retry-After header in seconds. When the global running-instance cap is reached, creating or starting a service answers 503 {\"error\",\"code\":\"capacity_exhausted\"} with Retry-After: 5; stop a service or retry. /healthz and /openapi.json are exempt.","title":"MicroSaaS.app control-plane API","version":"0.1.0"},"openapi":"3.0.3","paths":{"/healthz":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"ok":{"type":"boolean"},"reconciler_age_s":{"type":"integer"},"reconciler_last_ok":{"type":"integer"}},"required":["ok","reconciler_age_s","reconciler_last_ok"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"Liveness plus reconciler freshness (for the status page)","x-sandbox":true}},"/openapi.json":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"ok":{"type":"boolean"}},"required":["ok"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"This document","x-sandbox":true}},"/v1/account":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"active_ram_mb":{"type":"integer"},"active_services":{"type":"integer"},"plan":{"properties":{"active_hours_per_month":{"type":"integer"},"api_rate_per_s":{"type":"integer"},"billing_interval":{"type":"string"},"core_hours_per_month":{"type":"number"},"id":{"type":"string"},"idle_delete_days":{"type":"integer"},"invite_only":{"type":"boolean"},"max_active_accounts":{"nullable":true},"max_active_ram_mb":{"type":"integer"},"max_concurrent_active":{"type":"integer"},"max_services":{"type":"integer"},"max_storage_chunks":{"type":"integer"},"max_tokens":{"type":"integer"},"max_ttl_s":{"type":"integer"},"mem_gib_hours_per_month":{"type":"number"},"name":{"type":"string"},"outbound_mb_per_month":{"type":"integer"},"storage_gib_hours_per_month":{"type":"number"}},"required":["active_hours_per_month","api_rate_per_s","billing_interval","core_hours_per_month","id","idle_delete_days","invite_only","max_active_ram_mb","max_concurrent_active","max_services","max_storage_chunks","max_tokens","max_ttl_s","mem_gib_hours_per_month","name","outbound_mb_per_month","storage_gib_hours_per_month"],"type":"object"},"scope":{"type":"string"},"tenant":{"properties":{"balance_micro":{"type":"integer"},"created":{"type":"integer"},"deleting":{"type":"boolean"},"id":{"type":"string"},"name":{"type":"string"},"operator":{"type":"boolean"},"plan":{"type":"string"}},"required":["balance_micro","created","deleting","id","name","operator","plan"],"type":"object"}},"required":["active_ram_mb","active_services","plan","scope","tenant"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Tenant and caller scope","x-required-scope":"read","x-sandbox":true}},"/v1/audit":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"action":{"type":"string"},"actor":{"type":"string"},"at":{"type":"integer"},"detail":{"type":"string"},"id":{"type":"integer"},"target":{"type":"string"},"tenant":{"type":"string"}},"required":["action","actor","at","detail","id","target","tenant"],"type":"object"},"type":"array"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Audit trail for the tenant (operators: all entries, including reconciler actions)","x-required-scope":"admin"}},"/v1/auth/github/callback":{"get":{"responses":{"302":{"content":{"application/json":{"schema":{"properties":{},"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"Verify state, exchange the code, upsert user and personal tenant, set the session cookie, 302 to the console /profile (or /login?error=...)","x-auth":"public"}},"/v1/auth/github/start":{"get":{"responses":{"302":{"content":{"application/json":{"schema":{"properties":{},"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"302 to the GitHub authorize page (PKCE, 10 minute state); optional return_to on the console origin","x-auth":"public"}},"/v1/auth/logout":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"ok":{"type":"boolean"}},"required":["ok"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"End the session and clear the cookie (needs X-MSAAS-CSRF)","x-auth":"session"}},"/v1/auth/oidc/github":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"token":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"expires_at":{"type":"integer"},"scopes":{"items":{"type":"string"},"type":"array"},"tenant":{"type":"string"},"token":{"type":"string"}},"required":["expires_at","scopes","tenant","token"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"Exchange a GitHub Actions OIDC JWT (audience microsaas) for a 15-minute deploy-scope token for the tenant a trust rule maps the repository/ref/environment to; never admin. Every failure is the same 403 oidc_denied; 404 unless OIDC trust is configured"}},"/v1/auth/session":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"csrf_token":{"type":"string"},"expires_at":{"type":"integer"},"is_authenticated":{"type":"boolean"},"user_id":{"type":"string"}},"required":["csrf_token","expires_at","is_authenticated","user_id"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"Is the cookie session valid; returns expires_at and the per-session CSRF token","x-auth":"public"}},"/v1/billing/checkout":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"interval":{"type":"string"},"plan":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"url":{"type":"string"}},"required":["url"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Start a subscription checkout for a plan and interval; returns the hosted checkout URL. 501 unless configured","x-required-scope":"admin"}},"/v1/billing/topup":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"applied":{"type":"boolean"},"balance_micro":{"type":"integer"},"reference":{"type":"string"}},"required":["applied","balance_micro","reference"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"x402 prepaid top-up. Without X-PAYMENT: 402 with the payment requirements (x402Version, accepts[]). With X-PAYMENT: settles through the facilitator and credits once. 501 unless configured","x-required-scope":"deploy"}},"/v1/billing/x402":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"applied":{"type":"boolean"},"balance_micro":{"type":"integer"},"reference":{"type":"string"}},"required":["applied","balance_micro","reference"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Same settlement as /v1/billing/topup for a client that already holds an X-PAYMENT header (400 payment_missing without it)","x-required-scope":"deploy"}},"/v1/catalogue":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"memory_mb_default":{"type":"integer"},"memory_mb_min":{"type":"integer"},"protocols":{"items":{"type":"string"},"type":"array"},"status":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_default_s":{"type":"integer"},"ttl_max_s":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["category","description","id","memory_mb_default","memory_mb_min","protocols","status","storage_chunks","ttl_default_s","ttl_max_s","volume_mb"],"type":"object"},"type":"array"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"List deployable services","x-required-scope":"read","x-sandbox":true}},"/v1/catalogue/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"api":{"items":{"properties":{"auth":{"type":"string"},"endpoints":{"items":{"properties":{"auth":{"type":"string"},"method":{"type":"string"},"path":{"type":"string"},"summary":{"type":"string"}},"required":["auth","method","path","summary"],"type":"object"},"type":"array"},"kind":{"type":"string"},"name":{"type":"string"},"port":{"type":"integer"},"protocol":{"type":"string"}},"required":["auth","endpoints","kind","name","port","protocol"],"type":"object"},"type":"array"},"category":{"type":"string"},"config":{"items":{"properties":{"default":{"type":"string"},"description":{"type":"string"},"env":{"type":"string"},"key":{"type":"string"},"min":{"type":"integer"},"required":{"type":"boolean"},"restart_required":{"type":"boolean"},"secret":{"type":"boolean"},"settable":{"type":"boolean"},"source":{"type":"string"},"type":{"type":"string"}},"type":"object"},"type":"array"},"description":{"type":"string"},"files":{"items":{},"type":"array"},"generated_secrets":{"items":{"properties":{"bytes":{"type":"integer"},"env":{"type":"string"},"hex_chars":{"type":"integer"},"reveal":{"type":"boolean"}},"required":["bytes","env","hex_chars","reveal"],"type":"object"},"type":"array"},"id":{"type":"string"},"ports":{"items":{"properties":{"auth":{"type":"string"},"port":{"type":"integer"},"protocol":{"type":"string"}},"required":["auth","port","protocol"],"type":"object"},"type":"array"},"resources":{"properties":{"memory_mb_default":{"type":"integer"},"memory_min_mb":{"type":"integer"},"storage_chunks":{"type":"integer"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["memory_mb_default","memory_min_mb","storage_chunks","vcpus","volume_mb"],"type":"object"},"status":{"type":"string"},"verified":{"type":"string"}},"required":["api","category","description","files","generated_secrets","id","ports","resources","status","verified"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Full contract of one service: resources, ports, generated secrets, config keys (env, type, default, range, settable), config files and the service's own API","x-required-scope":"read","x-sandbox":true}},"/v1/keys":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"created":{"type":"integer"},"id":{"type":"string"},"label":{"type":"string"},"scope":{"type":"string"}},"required":["created","id","label","scope"],"type":"object"},"type":"array"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"List this tenant's active API keys (id, scope, label, created); the secret is never returned after creation","x-required-scope":"admin"},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"label":{"type":"string"},"scope":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"string"},"key":{"type":"string"},"scope":{"type":"string"}},"required":["id","key","scope"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Create an API key for this tenant","x-required-scope":"admin"}},"/v1/keys/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"ok":{"type":"boolean"}},"required":["ok"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Revoke an API key","x-required-scope":"admin"}},"/v1/me":{"delete":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"confirm":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"services_scheduled":{"type":"integer"},"status":{"type":"string"},"tokens_revoked":{"type":"integer"}},"required":["services_scheduled","status","tokens_revoked"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"Start account deletion: revoke tokens and sessions, schedule service deletion (session only)","x-auth":"session"},"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"avatar_url":{"type":"string"},"created_at":{"type":"integer"},"display_name":{"nullable":true},"email":{"type":"string"},"id":{"type":"string"},"last_login_at":{"type":"integer"},"login":{"type":"string"},"name":{"type":"string"},"notification_email":{"nullable":true},"tenant":{"properties":{"credits_micro":{"type":"integer"},"id":{"type":"string"},"plan":{"type":"string"},"services_count":{"type":"integer"}},"required":["credits_micro","id","plan","services_count"],"type":"object"}},"required":["avatar_url","created_at","email","id","last_login_at","login","name","tenant"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"Profile and personal tenant","x-auth":"session-or-token"},"patch":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"display_name":{"type":"string"},"notification_email":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"avatar_url":{"type":"string"},"created_at":{"type":"integer"},"display_name":{"nullable":true},"email":{"type":"string"},"id":{"type":"string"},"last_login_at":{"type":"integer"},"login":{"type":"string"},"name":{"type":"string"},"notification_email":{"nullable":true},"tenant":{"properties":{"credits_micro":{"type":"integer"},"id":{"type":"string"},"plan":{"type":"string"},"services_count":{"type":"integer"}},"required":["credits_micro","id","plan","services_count"],"type":"object"}},"required":["avatar_url","created_at","email","id","last_login_at","login","name","tenant"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"Update display_name and notification_email (null clears)","x-auth":"session-or-token"}},"/v1/sandbox/token":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"base_url":{"type":"string"},"expires_at":{"type":"integer"},"token":{"type":"string"}},"required":["base_url","expires_at","token"],"type":"object"}}},"description":"ok"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"Mint a one-hour token for the docs sandbox (session + CSRF, or a user access token); 10 per minute"}},"/v1/services":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"services":{"items":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"},"type":"array"}},"required":["services"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"List the tenant's services","x-required-scope":"read","x-sandbox":true},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"config":{"additionalProperties":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"Service configuration for the keys marked settable in GET /v1/catalogue/{id}; unknown, non-settable or invalid keys are rejected with 400 bad_config listing every error.","type":"object"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"service":{"type":"string"},"ttl_s":{"type":"integer"}},"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"402":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["insufficient_credit"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Not enough credit"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["plan_limit","instance_limit","allowance_exhausted","free_capacity_reached","rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Plan, allowance or free-tier limit reached, or rate limit","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"503":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["capacity_exhausted"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Global running-instance cap reached; retry after the Retry-After seconds","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Provision a service (async, 202); budget and quota checked","x-required-scope":"deploy","x-sandbox":true}},"/v1/services/metrics":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"services":{"items":{"properties":{"error":{"nullable":true},"id":{"type":"string"},"metrics":{"properties":{"cpu_time_ms":{"type":"integer"},"rss_bytes":{"type":"integer"},"rx_bytes":{"type":"integer"},"state":{"type":"string"},"tx_bytes":{"type":"integer"},"uptime_ms":{"type":"integer"}},"required":["cpu_time_ms","rss_bytes","rx_bytes","state","tx_bytes","uptime_ms"],"type":"object"},"name":{"type":"string"}},"required":["id","metrics","name"],"type":"object"},"type":"array"},"truncated":{"type":"boolean"}},"required":["services","truncated"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Runtime counters of the tenant's running services in one call (at most 20, oldest first; truncated is true beyond that). Each item carries metrics (same fields as one service) or, when the platform call failed, error {error, code} while the others still answer","x-required-scope":"read","x-sandbox":true}},"/v1/services/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Delete a service and its volume (async)","x-required-scope":"deploy","x-sandbox":true},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Get one service","x-required-scope":"read","x-sandbox":true}},"/v1/services/{id}/extend":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"ttl_s":{"type":"integer"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Lengthen a service's lifetime by whole hours, up to the plan's maximum TTL","x-required-scope":"deploy","x-sandbox":true}},"/v1/services/{id}/logs":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"lines":{"type":"integer"},"logs":{"type":"string"}},"required":["lines","logs"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Newest log lines of one service (query tail, 1..=1000, default 100); bearer tokens, platform token formats and the service's own secrets are redacted","x-required-scope":"deploy","x-sandbox":true}},"/v1/services/{id}/metrics":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"cpu_time_ms":{"type":"integer"},"rss_bytes":{"type":"integer"},"rx_bytes":{"type":"integer"},"state":{"type":"string"},"tx_bytes":{"type":"integer"},"uptime_ms":{"type":"integer"}},"required":["cpu_time_ms","rss_bytes","rx_bytes","state","tx_bytes","uptime_ms"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Runtime counters of one service: state, cpu_time_ms, rss_bytes, rx_bytes, tx_bytes and uptime_ms (since the last boot, null when not reported)","x-required-scope":"read","x-sandbox":true}},"/v1/services/{id}/start":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"402":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["insufficient_credit"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Not enough credit"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["plan_limit","instance_limit","allowance_exhausted","free_capacity_reached","rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Plan, allowance or free-tier limit reached, or rate limit","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"503":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["capacity_exhausted"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Global running-instance cap reached; retry after the Retry-After seconds","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Start a stopped service","x-required-scope":"deploy","x-sandbox":true}},"/v1/services/{id}/stop":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"config":{"properties":{"max_db_bytes":{"type":"string"}},"type":"object"},"crash_loop":{"type":"boolean"},"created":{"type":"integer"},"expires_at":{"type":"integer"},"health":{"type":"string"},"id":{"type":"string"},"last_error":{"type":"string"},"memory_mb":{"type":"integer"},"name":{"type":"string"},"restarts":{"type":"integer"},"secrets":{"properties":{"API_KEY":{"type":"string"}},"type":"object"},"service":{"type":"string"},"state":{"type":"string"},"storage_chunks":{"type":"integer"},"ttl_s":{"type":"integer"},"url":{"type":"string"},"vcpus":{"type":"integer"},"volume_mb":{"type":"integer"}},"required":["crash_loop","created","expires_at","health","id","last_error","memory_mb","name","restarts","service","state","storage_chunks","ttl_s","url","vcpus","volume_mb"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"404":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["not_found"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"No such resource (the same body for another tenant's id)"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Stop a running service (volume kept, still billed)","x-required-scope":"deploy","x-sandbox":true}},"/v1/tokens":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"tokens":{"items":{"properties":{"created_at":{"type":"integer"},"expires_at":{"type":"integer"},"id":{"type":"string"},"last_used_at":{"type":"integer"},"name":{"type":"string"},"prefix":{"type":"string"},"revoked_at":{"nullable":true},"scopes":{"items":{"type":"string"},"type":"array"}},"required":["created_at","expires_at","id","last_used_at","name","prefix","scopes"],"type":"object"},"type":"array"}},"required":["tokens"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"List access tokens (never the secret)","x-auth":"session-or-token"},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"expires_in_days":{"type":"integer"},"name":{"type":"string"},"scopes":{"items":{"type":"string"},"type":"array"}},"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"created_at":{"type":"integer"},"expires_at":{"type":"integer"},"id":{"type":"string"},"last_used_at":{"type":"integer"},"name":{"type":"string"},"prefix":{"type":"string"},"revoked_at":{"nullable":true},"scopes":{"items":{"type":"string"},"type":"array"},"token":{"type":"string"}},"required":["created_at","expires_at","id","last_used_at","name","prefix","scopes","token"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"Create an access token; the secret is returned once","x-auth":"session-or-token"}},"/v1/tokens/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"string"},"ok":{"type":"boolean"}},"required":["id","ok"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"Revoke a token immediately","x-auth":"session-or-token"}},"/v1/tokens/{id}/rotate":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"created_at":{"type":"integer"},"expires_at":{"type":"integer"},"id":{"type":"string"},"last_used_at":{"type":"integer"},"name":{"type":"string"},"prefix":{"type":"string"},"revoked_at":{"nullable":true},"scopes":{"items":{"type":"string"},"type":"array"},"token":{"type":"string"}},"required":["created_at","expires_at","id","last_used_at","name","prefix","scopes","token"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]},{"cookie":[]}],"summary":"New secret with the same name, scopes and lifetime; the old token is revoked","x-auth":"session-or-token"}},"/v1/usage":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"balance_micro":{"type":"integer"},"from":{"type":"integer"},"records":{"items":{"properties":{"core_s":{"type":"integer"},"cost_micro":{"type":"integer"},"instance":{"type":"string"},"interval_s":{"type":"integer"},"interval_start":{"type":"integer"},"plan":{"type":"string"},"ram_mb_s":{"type":"integer"},"running_s":{"type":"integer"},"rx_bytes":{"type":"integer"},"tenant":{"type":"string"},"tx_bytes":{"type":"integer"},"units":{"type":"integer"},"vcpu_ms":{"type":"integer"},"volume_mb_s":{"type":"integer"}},"required":["core_s","cost_micro","instance","interval_s","interval_start","plan","ram_mb_s","running_s","rx_bytes","tenant","tx_bytes","units","vcpu_ms","volume_mb_s"],"type":"object"},"type":"array"},"tenant":{"type":"string"},"to":{"type":"integer"},"totals":{"properties":{"cost_micro":{"type":"integer"},"ram_mb_s":{"type":"integer"},"vcpu_s":{"type":"number"},"volume_gb_h":{"type":"number"}},"required":["cost_micro","ram_mb_s","vcpu_s","volume_gb_h"],"type":"object"},"units":{"properties":{"allowance":{"properties":{"core_hours":{"properties":{"limit":{"type":"number"},"remaining":{"type":"number"},"used":{"type":"number"}},"required":["limit","remaining","used"],"type":"object"},"mem_gib_hours":{"properties":{"limit":{"type":"number"},"remaining":{"type":"number"},"used":{"type":"number"}},"required":["limit","remaining","used"],"type":"object"},"period_end":{"type":"integer"},"period_start":{"type":"integer"},"storage_gib_hours":{"properties":{"limit":{"type":"number"},"remaining":{"type":"number"},"used":{"type":"number"}},"required":["limit","remaining","used"],"type":"object"}},"required":["core_hours","mem_gib_hours","period_end","period_start","storage_gib_hours"],"type":"object"},"core_hours":{"type":"number"},"mem_gib_hours":{"type":"number"},"running_hours":{"type":"number"},"storage_gib_hours":{"type":"number"}},"required":["allowance","core_hours","mem_gib_hours","running_hours","storage_gib_hours"],"type":"object"}},"required":["balance_micro","from","records","tenant","to","totals","units"],"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["unauthorized"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Missing, invalid or revoked credential"},"403":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["forbidden","tenant_unavailable"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Scope too low or tenant unavailable"},"429":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["rate_limited"],"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"Rate limit reached","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}}},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"security":[{"bearer":[]}],"summary":"Usage ledger and balance; query from, to (unix seconds)","x-required-scope":"read","x-sandbox":true}},"/v1/webhooks/paddle":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"id":{"type":"string"},"status":{"type":"string"}},"type":"object"},"event_id":{"type":"string"},"event_type":{"type":"string"},"occurred_at":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"status":{"type":"string"}},"required":["status"],"type":"object"}}},"description":"ok"},"default":{"content":{"application/json":{"schema":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["code","error"],"type":"object"}}},"description":"error"}},"summary":"Payment provider webhook (raw body, Paddle-Signature header; the signature is the only credential). 404 unless Paddle is configured; 400 bad signature or event; replays answer duplicate"}}},"servers":[{"url":"https://api.microsaas.app","description":"Production API (documentation only; the console sandbox is login-gated)"}]}