{"auth":{"api_key":{"example":"X-API-Key: m27_your_key_here","header":"X-API-Key","how_to_get":"POST /api/v1/api-keys (needs JWT first), or generate at platform.marc27.com/dashboard/api-keys"},"description":"Two methods. API key for agents (simplest, never expires). JWT for browser sessions.","jwt":{"header":"Authorization: Bearer <token>","how_to_get":"POST /api/v1/auth/token (with Supabase JWT), or device flow via POST /api/v1/auth/device/start"}},"cli":{"auth":"export MARC27_API_KEY=m27_your_key","description":"PRISM CLI — fastest way for agents to interact.","install":"pip install prism-platform","quick_start":["prism query --platform --semantic 'your question' --json","prism query --platform 'Inconel 718' | grep MAT","prism agent  # prints full command guide"]},"description":"Infrastructure for materials science — knowledge graph, LLM, compute, and collaboration.","error_handling":{"description":"All endpoints return structured errors. Smart 404s suggest correct endpoints.","format":{"error":{"code":"string","message":"string"},"suggestions":[{"description":"...","method":"GET","path":"/api/v1/..."}]},"hint":"If you get a 404, read the suggestions array — it tells you the correct endpoint."},"graphql":{"description":"GraphQL — query multiple services in one request. Preferred over REST for complex queries.","endpoint":"POST /api/v1/graphql","mutations":{"cancelComputeJob":"mutation { cancelComputeJob(id: \"...\") }","submitComputeJob":"mutation { submitComputeJob(input: { image: \"marc27/lammps\", inputs: \"{}\", gpuType: \"A100-80GB\" }) { id status } }","submitIngestJob":"mutation { submitIngestJob(input: { corpusId: \"...\", sourceUrl: \"...\" }) { id status } }"},"queries":{"computeGpus":"{ computeGpus { gpuType provider pricePerHourUsd vramGb } }","corpora":"{ corpora { name slug kind entryCount } }","deployments":"{ deployments(status: \"running\", limit: 5) { id name status target gpuType costUsd endpointUrl } }","discourseSpecs":"{ discourseSpecs(limit: 5) { id slug name version } }","embeddingStats":"{ embeddingStats { count } }","entity":"{ entity(name: \"Titanium\") { name entityType props neighbors(limit: 5) { target { name entityType } relType count } } }","graphStats":"{ graphStats { nodes edges entityTypes } }","llmModels":"{ llmModels(provider: \"anthropic\", limit: 5) { modelId displayName inputPrice outputPrice contextWindow } }","marketplace":"{ marketplace(limit: 5) { name slug resourceType } }","me":"{ me { id displayName avatarUrl } }","nodes":"{ nodes(limit: 5) { id name status visibility lastSeen pricePerHour } }","paths":"{ paths(from: \"Nickel\", to: \"Creep Resistance\", maxHops: 3) }","provenance":"{ provenance(entityType: \"CHM\", entityId: \"Nickel\") }","search":"{ search(term: \"nickel\", limit: 5) { name entityType label props } }","semanticSearch":"{ semanticSearch(query: \"thermal protection ablative\", limit: 3) { docId content similarity } }"}},"platform":"MARC27","services":{"admin":{"endpoint_count":18,"endpoints":[{"description":"List marketplace review queue","method":"GET","path":"/api/v1/admin/review-queue"},{"description":"Approve marketplace resource","method":"POST","path":"/api/v1/admin/review/{id}/approve"},{"description":"Reject marketplace resource","example_body":"{\"reason\":\"...\"}","method":"POST","path":"/api/v1/admin/review/{id}/reject"},{"description":"Suspend outbound API calls","method":"POST","path":"/api/v1/admin/ops/suspend"},{"description":"Resume outbound API calls","method":"POST","path":"/api/v1/admin/ops/resume"},{"description":"Get outbound API kill-switch status","method":"GET","path":"/api/v1/admin/ops/status"},{"description":"List audit logs","method":"GET","path":"/api/v1/admin/audit"},{"description":"Count audit logs","method":"GET","path":"/api/v1/admin/audit/count"},{"description":"List managed containers","method":"GET","path":"/api/v1/admin/containers"},{"description":"Inspect managed container","method":"GET","path":"/api/v1/admin/containers/{id}"},{"description":"Kill managed container","method":"DELETE","path":"/api/v1/admin/containers/{id}"},{"description":"Get managed container logs","method":"GET","path":"/api/v1/admin/containers/{id}/logs"},{"description":"Direct object storage upload","method":"POST","path":"/api/v1/admin/storage/upload"},{"description":"Create presigned upload URL","example_body":"{\"key\":\"resources/model.bin\"}","method":"POST","path":"/api/v1/admin/storage/presign-upload"},{"description":"Create presigned download URL","example_body":"{\"key\":\"resources/model.bin\"}","method":"POST","path":"/api/v1/admin/storage/presign-download"},{"description":"List object storage keys","method":"GET","path":"/api/v1/admin/storage/list"},{"description":"Delete object storage key","example_body":"{\"key\":\"resources/model.bin\"}","method":"POST","path":"/api/v1/admin/storage/delete"},{"description":"Check object existence","method":"GET","path":"/api/v1/admin/storage/exists"}]},"agent":{"endpoint_count":1,"endpoints":[{"description":"Full endpoint and capability map","method":"GET","path":"/api/v1/agent/capabilities"}]},"api-keys":{"endpoint_count":3,"endpoints":[{"description":"List API keys","method":"GET","path":"/api/v1/api-keys"},{"description":"Create an API key","example_body":"{\"name\":\"my-key\",\"scopes\":[\"read\",\"write\"]}","method":"POST","path":"/api/v1/api-keys"},{"description":"Delete an API key","method":"DELETE","path":"/api/v1/api-keys/{id}"}]},"auth":{"endpoint_count":7,"endpoints":[{"description":"Exchange Supabase JWT for platform JWT","example_body":"{\"supabase_token\":\"...\"}","method":"POST","path":"/api/v1/auth/token"},{"description":"Refresh platform token","example_body":"{\"refresh_token\":\"m27r_...\"}","method":"POST","path":"/api/v1/auth/refresh"},{"description":"Revoke a refresh token","example_body":"{\"refresh_token\":\"m27r_...\"}","method":"POST","path":"/api/v1/auth/logout"},{"description":"Start device flow login","example_body":"{\"client_id\":\"prism\"}","method":"POST","path":"/api/v1/auth/device/start"},{"description":"Poll device flow authorization status","example_body":"{\"device_code\":\"...\"}","method":"POST","path":"/api/v1/auth/device/poll"},{"description":"Approve a device flow code","example_body":"{\"user_code\":\"ABCD-EFGH\"}","method":"POST","path":"/api/v1/auth/device/approve"},{"description":"Deny a device flow code","example_body":"{\"user_code\":\"ABCD-EFGH\"}","method":"POST","path":"/api/v1/auth/device/deny"}]},"billing":{"endpoint_count":7,"endpoints":[{"description":"Get credit balance for your org","method":"GET","path":"/api/v1/billing/balance"},{"description":"Usage breakdown by service/model","method":"GET","path":"/api/v1/billing/usage?period=monthly"},{"description":"Paginated transaction ledger","method":"GET","path":"/api/v1/billing/history?page=1&per_page=50"},{"description":"Current credit pricing table (public)","method":"GET","path":"/api/v1/billing/prices"},{"description":"Available credit packages for purchase","method":"GET","path":"/api/v1/billing/packages"},{"description":"Create Stripe Checkout for credit purchase","example_body":"{\"package\":\"starter\"}","method":"POST","path":"/api/v1/billing/topup"},{"description":"Stripe billing webhook","example_body":"{\"type\":\"checkout.session.completed\"}","method":"POST","path":"/api/v1/billing/webhook"}]},"callbacks":{"endpoint_count":1,"endpoints":[{"description":"Receive lab booking callback","example_body":"{\"status\":\"confirmed\"}","method":"POST","path":"/api/v1/callbacks/booking/{booking_id}"}]},"compute":{"endpoint_count":12,"endpoints":[{"description":"List available GPUs + pricing","method":"GET","path":"/api/v1/compute/gpus"},{"description":"List compute providers","method":"GET","path":"/api/v1/compute/providers"},{"description":"Submit a compute job","example_body":"{\"image\":\"my-model\",\"gpu_type\":\"A100-80GB\",\"inputs\":{}}","method":"POST","path":"/api/v1/compute/submit"},{"description":"Estimate job cost","example_body":"{\"image\":\"my-model\",\"gpu_type\":\"A100-80GB\",\"inputs\":{}}","method":"POST","path":"/api/v1/compute/estimate"},{"description":"Get job status","method":"GET","path":"/api/v1/compute/{job_id}"},{"description":"Get job logs","method":"GET","path":"/api/v1/compute/{job_id}/logs"},{"description":"Cancel a job","method":"POST","path":"/api/v1/compute/{job_id}/cancel"},{"description":"List model deployments","method":"GET","path":"/api/v1/compute/deployments"},{"description":"Create a model deployment","example_body":"{\"name\":\"my-model\",\"image\":\"repo/image:tag\",\"target\":\"prism_node\"}","method":"POST","path":"/api/v1/compute/deployments"},{"description":"Get model deployment details","method":"GET","path":"/api/v1/compute/deployments/{id}"},{"description":"Stop a model deployment","method":"DELETE","path":"/api/v1/compute/deployments/{id}"},{"description":"Run a deployment health check","method":"GET","path":"/api/v1/compute/deployments/{id}/health"}]},"discourse":{"endpoint_count":6,"endpoints":[{"description":"List discourse specs","method":"GET","path":"/api/v1/discourse/specs"},{"description":"Create a discourse spec","example_body":"{\"slug\":\"my-discourse\",\"yaml\":\"...\"}","method":"POST","path":"/api/v1/discourse/specs"},{"description":"Get discourse spec","method":"GET","path":"/api/v1/discourse/specs/{id}"},{"description":"Run a discourse instance","example_body":"{\"inputs\":{}}","method":"POST","path":"/api/v1/discourse/run/{spec_id}"},{"description":"Get discourse instance","method":"GET","path":"/api/v1/discourse/{instance_id}"},{"description":"List discourse turns","method":"GET","path":"/api/v1/discourse/{instance_id}/turns"}]},"email":{"endpoint_count":1,"endpoints":[{"description":"Send an email from an authenticated identity","example_body":"{\"to\":\"user@example.com\",\"subject\":\"Hello\",\"body\":\"...\"}","method":"POST","path":"/api/v1/email/send"}]},"graphql":{"endpoint_count":2,"endpoints":[{"description":"GraphQL query","example_body":"{\"query\":\"{ graphStats { nodes edges } }\"}","method":"POST","path":"/api/v1/graphql"},{"description":"GraphQL endpoint guide","method":"GET","path":"/api/v1/graphql"}]},"health":{"endpoint_count":3,"endpoints":[{"description":"Liveness check","method":"GET","path":"/health"},{"description":"Readiness check","method":"GET","path":"/health/ready"},{"description":"Prometheus-style metrics","method":"GET","path":"/health/metrics"}]},"invites":{"endpoint_count":1,"endpoints":[{"description":"Accept an invite token","example_body":"{\"token\":\"...\"}","method":"POST","path":"/api/v1/invites/accept"}]},"jobs":{"endpoint_count":4,"endpoints":[{"description":"Submit a queue-backed platform job","example_body":"{\"job_type\":\"simulation\",\"project_id\":\"...\",\"payload\":{}}","method":"POST","path":"/api/v1/jobs"},{"description":"Get platform job details","method":"GET","path":"/api/v1/jobs/{id}"},{"description":"Cancel a platform job","method":"POST","path":"/api/v1/jobs/{id}/cancel"},{"description":"Stream platform job events","method":"GET","path":"/api/v1/jobs/{id}/events"}]},"knowledge":{"endpoint_count":18,"endpoints":[{"description":"Graph node/edge counts","method":"GET","path":"/api/v1/knowledge/graph/stats"},{"description":"Fulltext entity search","method":"GET","path":"/api/v1/knowledge/graph/search?q=titanium&limit=5"},{"description":"Entity + neighbors","method":"GET","path":"/api/v1/knowledge/graph/entity/{name}"},{"description":"Find paths between graph entities","method":"GET","path":"/api/v1/knowledge/graph/paths"},{"description":"Seed graph data","example_body":"{\"source_url\":\"...\"}","method":"POST","path":"/api/v1/knowledge/graph/seed"},{"description":"Ingest graph entities and relationships","example_body":"{\"entities\":[],\"relationships\":[]}","method":"POST","path":"/api/v1/knowledge/graph/ingest"},{"description":"Semantic vector search","example_body":"{\"query\":\"creep resistant superalloy\",\"limit\":5}","method":"POST","path":"/api/v1/knowledge/search"},{"description":"Embed text into vector store","example_body":"{\"doc_id\":\"my-doc\",\"content\":\"...\"}","method":"POST","path":"/api/v1/knowledge/embed"},{"description":"Bulk embed documents into vector store","example_body":"{\"documents\":[]}","method":"POST","path":"/api/v1/knowledge/embed/bulk"},{"description":"Embedding store statistics","method":"GET","path":"/api/v1/knowledge/embeddings/stats"},{"description":"List all corpora","method":"GET","path":"/api/v1/knowledge/catalog"},{"description":"Get corpus details","method":"GET","path":"/api/v1/knowledge/catalog/{slug}"},{"description":"Submit an ingest job","example_body":"{\"corpus_id\":\"...\",\"source_url\":\"...\"}","method":"POST","path":"/api/v1/knowledge/ingest-job"},{"description":"Get ingest job status","method":"GET","path":"/api/v1/knowledge/ingest-job/{job_id}"},{"description":"List ingest jobs","method":"GET","path":"/api/v1/knowledge/ingest-jobs"},{"description":"RLM research query (SSE stream)","example_body":"{\"question\":\"...\",\"depth\":1}","method":"POST","path":"/api/v1/knowledge/research/query"},{"description":"Run a web-backed research search","example_body":"{\"query\":\"...\"}","method":"POST","path":"/api/v1/knowledge/research/web-search"},{"description":"Knowledge service tool list","method":"GET","path":"/api/v1/knowledge/capabilities"}]},"marketplace":{"endpoint_count":13,"endpoints":[{"description":"List marketplace resources","method":"GET","path":"/api/v1/marketplace?status=approved"},{"description":"Same as above (alias)","method":"GET","path":"/api/v1/marketplace/resources"},{"description":"Search resources","method":"GET","path":"/api/v1/marketplace/search?q=titanium"},{"description":"Publish a resource","example_body":"{\"resource_type\":\"model\",\"name\":\"...\",\"slug\":\"...\"}","method":"POST","path":"/api/v1/marketplace"},{"description":"Get marketplace resource","method":"GET","path":"/api/v1/marketplace/{slug}"},{"description":"Update marketplace resource","example_body":"{\"description\":\"Updated description\"}","method":"PATCH","path":"/api/v1/marketplace/{slug}"},{"description":"Delete marketplace resource","method":"DELETE","path":"/api/v1/marketplace/{slug}"},{"description":"Submit marketplace resource for review","method":"POST","path":"/api/v1/marketplace/{slug}/submit"},{"description":"List marketplace resource versions","method":"GET","path":"/api/v1/marketplace/{slug}/versions"},{"description":"Create marketplace resource version","example_body":"{\"version\":\"1.0.0\"}","method":"POST","path":"/api/v1/marketplace/{slug}/versions"},{"description":"Record marketplace resource download","method":"POST","path":"/api/v1/marketplace/{slug}/download"},{"description":"Grant project access to a resource","example_body":"{\"project_id\":\"...\",\"resource_id\":\"...\"}","method":"POST","path":"/api/v1/marketplace/grants"},{"description":"Revoke project access to a resource","method":"DELETE","path":"/api/v1/marketplace/grants/{project_id}/{resource_id}"}]},"nodes":{"endpoint_count":10,"endpoints":[{"description":"List registered nodes","method":"GET","path":"/api/v1/nodes"},{"description":"List currently connected nodes","method":"GET","path":"/api/v1/nodes/live"},{"description":"Connect compute node WebSocket","method":"GET","path":"/api/v1/nodes/connect"},{"description":"Register a node (REST)","example_body":"{\"name\":\"my-node\",\"capabilities\":{}}","method":"POST","path":"/api/v1/nodes/register"},{"description":"Get node details","method":"GET","path":"/api/v1/nodes/{id}"},{"description":"Deregister a node","method":"DELETE","path":"/api/v1/nodes/{id}"},{"description":"Node heartbeat","method":"POST","path":"/api/v1/nodes/{id}/heartbeat"},{"description":"Get node E2EE public key","method":"GET","path":"/api/v1/nodes/{id}/public-key"},{"description":"E2EE key exchange","example_body":"{\"public_key\":\"base64...\"}","method":"POST","path":"/api/v1/nodes/{id}/exchange-key"},{"description":"Clean up stale node registrations","method":"POST","path":"/api/v1/nodes/cleanup"}]},"orgs":{"endpoint_count":9,"endpoints":[{"description":"List organizations","method":"GET","path":"/api/v1/orgs"},{"description":"Create an organization","example_body":"{\"name\":\"My Lab\",\"slug\":\"my-lab\"}","method":"POST","path":"/api/v1/orgs"},{"description":"Get organization details","method":"GET","path":"/api/v1/orgs/{id}"},{"description":"Update an organization","example_body":"{\"name\":\"New Lab Name\"}","method":"PATCH","path":"/api/v1/orgs/{id}"},{"description":"Delete an organization","method":"DELETE","path":"/api/v1/orgs/{id}"},{"description":"List organization members","method":"GET","path":"/api/v1/orgs/{id}/members"},{"description":"Add an organization member","example_body":"{\"user_id\":\"...\",\"role\":\"member\"}","method":"POST","path":"/api/v1/orgs/{id}/members"},{"description":"Update an organization member role","example_body":"{\"role\":\"admin\"}","method":"PATCH","path":"/api/v1/orgs/{id}/members/{user_id}"},{"description":"Remove an organization member","method":"DELETE","path":"/api/v1/orgs/{id}/members/{user_id}"}]},"policy":{"endpoint_count":1,"endpoints":[{"description":"Check if an action is allowed (RBAC + data classification)","example_body":"{\"action\":\"read_data\",\"resource\":{\"resource_type\":\"corpus\",\"classification\":\"public\"}}","method":"POST","path":"/api/v1/policy/evaluate"}]},"projects":{"endpoint_count":26,"endpoints":[{"description":"List all user's projects","method":"GET","path":"/api/v1/projects"},{"description":"Create a project","example_body":"{\"name\":\"My Project\",\"slug\":\"my-project\",\"org_id\":\"...\"}","method":"POST","path":"/api/v1/projects"},{"description":"Get project details","method":"GET","path":"/api/v1/projects/{id}"},{"description":"Update a project","example_body":"{\"name\":\"New Project Name\"}","method":"PATCH","path":"/api/v1/projects/{id}"},{"description":"Delete a project","method":"DELETE","path":"/api/v1/projects/{id}"},{"description":"List jobs for a project","method":"GET","path":"/api/v1/projects/{id}/jobs"},{"description":"List project members","method":"GET","path":"/api/v1/projects/{project_id}/collab/members"},{"description":"Add a project member","example_body":"{\"user_id\":\"...\",\"role\":\"contributor\"}","method":"POST","path":"/api/v1/projects/{project_id}/collab/members"},{"description":"Update a project member role","example_body":"{\"role\":\"admin\"}","method":"PUT","path":"/api/v1/projects/{project_id}/collab/members/{user_id}"},{"description":"Remove a project member","method":"DELETE","path":"/api/v1/projects/{project_id}/collab/members/{user_id}"},{"description":"Create a project invite","example_body":"{\"email\":\"scientist@example.com\",\"role\":\"viewer\"}","method":"POST","path":"/api/v1/projects/{project_id}/collab/invite"},{"description":"List project invites","method":"GET","path":"/api/v1/projects/{project_id}/collab/invites"},{"description":"List project activity","method":"GET","path":"/api/v1/projects/{project_id}/collab/activity"},{"description":"Activate a corpus for a project","example_body":"{\"corpus_slug\":\"materials-project\"}","method":"POST","path":"/api/v1/projects/{project_id}/knowledge/activate"},{"description":"List project corpus activations","method":"GET","path":"/api/v1/projects/{project_id}/knowledge/activations"},{"description":"Deactivate a project corpus activation","method":"DELETE","path":"/api/v1/projects/{project_id}/knowledge/activations/{activation_id}"},{"description":"List LLM models","method":"GET","path":"/api/v1/projects/{project_id}/llm/models"},{"description":"LLM completion (SSE stream)","example_body":"{\"model\":\"claude-sonnet-4\",\"messages\":[{\"role\":\"user\",\"content\":\"...\"}]}","method":"POST","path":"/api/v1/projects/{project_id}/llm/stream"},{"description":"List LLM key hints for a project","method":"GET","path":"/api/v1/projects/{project_id}/llm-keys"},{"description":"Store an encrypted LLM API key","example_body":"{\"provider\":\"openai\",\"key\":\"sk-...\"}","method":"POST","path":"/api/v1/projects/{project_id}/llm-keys"},{"description":"Delete an LLM API key","method":"DELETE","path":"/api/v1/projects/{project_id}/llm-keys/{provider}"},{"description":"Rotate an encrypted LLM API key","example_body":"{\"key\":\"sk-...\"}","method":"POST","path":"/api/v1/projects/{project_id}/llm-keys/{provider}/rotate"},{"description":"List MCP service instances","method":"GET","path":"/api/v1/projects/{project_id}/mcp-services"},{"description":"Get MCP service instance details","method":"GET","path":"/api/v1/projects/{project_id}/mcp-services/{instance_id}"},{"description":"Proxy a request to an MCP service","example_body":"{\"path\":\"/tools/list\",\"body\":{}}","method":"POST","path":"/api/v1/projects/{project_id}/mcp-services/{instance_id}/proxy"},{"description":"Scale an MCP service instance","example_body":"{\"replicas\":1}","method":"POST","path":"/api/v1/projects/{project_id}/mcp-services/{instance_id}/scale"}]},"root":{"endpoint_count":1,"endpoints":[{"description":"Status page","method":"GET","path":"/"}]},"support":{"endpoint_count":4,"endpoints":[{"description":"List support tickets","method":"GET","path":"/api/v1/support/tickets"},{"description":"Create a ticket","example_body":"{\"description\":\"...\",\"type\":\"bug_report\"}","method":"POST","path":"/api/v1/support/tickets"},{"description":"Get support ticket","method":"GET","path":"/api/v1/support/tickets/{ticket_id}"},{"description":"Update support ticket","example_body":"{\"status\":\"resolved\"}","method":"PATCH","path":"/api/v1/support/tickets/{ticket_id}"}]},"usage":{"endpoint_count":4,"endpoints":[{"description":"Get usage metrics","method":"GET","path":"/api/v1/usage/user"},{"description":"Get current usage metrics","method":"GET","path":"/api/v1/usage/me"},{"description":"Get project usage","method":"GET","path":"/api/v1/usage/projects/{project_id}"},{"description":"List project usage ledger entries","method":"GET","path":"/api/v1/usage/projects/{project_id}/entries"}]},"users":{"endpoint_count":2,"endpoints":[{"description":"Get current user profile","method":"GET","path":"/api/v1/users/me"},{"description":"Update profile","example_body":"{\"display_name\":\"Dr. Smith\",\"orcid_id\":\"0000-0001\"}","method":"PATCH","path":"/api/v1/users/me"}]},"workflows":{"endpoint_count":6,"endpoints":[{"description":"List workflow instances","method":"GET","path":"/api/v1/workflows"},{"description":"Start a workflow","example_body":"{\"spec\":\"my-workflow\",\"inputs\":{}}","method":"POST","path":"/api/v1/workflows"},{"description":"List workflow specs","method":"GET","path":"/api/v1/workflows/specs"},{"description":"Register a workflow spec","example_body":"{\"spec_yaml\":\"...\",\"access\":\"public\"}","method":"POST","path":"/api/v1/workflows/specs"},{"description":"Get workflow instance","method":"GET","path":"/api/v1/workflows/{id}"},{"description":"Cancel workflow instance","method":"POST","path":"/api/v1/workflows/{id}/cancel"}]}},"total_endpoints":160,"version":"0.1.0"}