Platform API
MARC27 is infrastructure for materials science. One API gives you a materials knowledge graph built from published literature, semantic search and retrieval over that corpus, GPU compute for simulation and model inference, and a marketplace of models and datasets — with provenance recorded on every result.
Everything below is reachable over plain HTTPS with a single credential. Responses are JSON. Long-running work (ingestion, compute, agent runs) is submitted once and polled or streamed over Server-Sent Events.
Every endpoint under /api/v1 needs a credential unless noted otherwise.
/health and this page do not.
| Header | X-API-Key: m27_… |
| Lifetime | Does not expire until you delete it |
| How to get one | POST /api/v1/api-keys (needs a token first), or create one in the dashboard at platform.marc27.com |
| Header | Authorization: Bearer <token> |
| How to get one | POST /api/v1/auth/token with your sign-in token, or run the device flow from POST /api/v1/auth/device/start |
| Expiry | Short-lived. Rotate with POST /api/v1/auth/refresh; an expired token answers token_expired |
Confirm you can reach the API. No credential needed:
curl https://api.marc27.com/health
Now prove your credential works — this returns your own profile:
curl https://api.marc27.com/api/v1/users/me \
-H "X-API-Key: m27_your_key_here"
And a first real query — semantic search across the materials corpus:
curl https://api.marc27.com/api/v1/knowledge/search \
-H "X-API-Key: m27_your_key_here" \
-H "Content-Type: application/json" \
-d '{"query": "creep resistance in nickel superalloys", "limit": 5}'
One request can span the knowledge graph, platform resources and compute. Send queries
to POST /api/v1/graphql with the same credential as REST; opening
/api/v1/graphql in a browser gives you an interactive playground.
curl https://api.marc27.com/api/v1/graphql \
-H "X-API-Key: m27_your_key_here" \
-H "Content-Type: application/json" \
-d '{"query": "{ graphStats { nodes edges entityTypes } }"}'
search(term: String!, limit: Int! = 20): [Entity!]! entity(name: String!): Entity paths(from: String!, to: String!, maxHops: Int! = 3): [[String!]!]! graphStats: GraphStats! me: PlatformUser marketplace(resourceType: String, limit: Int! = 50, offset: Int! = 0): [MarketplaceResource!]! resource(slug: String!): MarketplaceResource corpora(domain: String, kind: String, limit: Int! = 50): [CorpusInfo!]! billingBalance: BillingBalance! agentRuns(limit: Int! = 20): [AgentRunInfo!]! agentRun(id: String!): AgentRunInfo jobs(status: String, limit: Int! = 20): [JobInfo!]! computeGpus: [GpuOfferingGql!]! computeJob(id: String!): ComputeJobGql computeEstimate(input: ComputeJobInput!): CostEstimateGql! embeddingStats: EmbeddingStats! provenance(entityType: String!, entityId: String!): [ProvenanceRecord!]! ingestJob(id: String!): IngestJobGql semanticSearch(query: String!, limit: Int! = 5, corpusId: String): [SearchResult!]! recall(query: String!, limit: Int! = 5, factLimit: Int! = 25): RecallResult! llmModels(provider: String, limit: Int! = 50): [LlmModel!]! deployments(status: String, limit: Int! = 20): [Deployment!]! discourseSpecs(limit: Int! = 20): [DiscourseSpec!]! nodes(status: String, limit: Int! = 50): [Node!]!
submitComputeJob(input: ComputeJobInput!): ComputeJobGql! cancelComputeJob(id: String!): Boolean! submitIngestJob(input: IngestJobInput!): IngestJobGql! createDeployment(projectId: String!, name: String!, image: String!, gpuType: String, target: String, budgetMaxUsd: Float): Deployment! stopDeployment(id: String!): Boolean! createDiscourseSpec(slug: String!, yaml: String!): DiscourseSpec!
Paths are shown in full. Anything taking a body expects
Content-Type: application/json.
Liveness, readiness and runtime metrics. No credential required.
/health/health/ready/health/metricsExchange a sign-in token for a platform token, or run the CLI device flow.
/api/v1/auth/token{"supabase_token":"..."}
/api/v1/auth/refresh{"refresh_token":"m27r_..."}
/api/v1/auth/logout{"refresh_token":"m27r_..."}
/api/v1/auth/device/start{"client_id":"prism"}
/api/v1/auth/device/poll{"device_code":"..."}
/api/v1/auth/device/approve{"user_code":"ABCD-EFGH","supabase_token":"eyJhbGciOi..."}
/api/v1/auth/device/deny{"user_code":"ABCD-EFGH","supabase_token":"eyJhbGciOi..."}
The profile behind the current credential.
/api/v1/users/me/api/v1/users/me{"display_name":"Dr. Smith","orcid_id":"0000-0001"}
Organisations own projects, billing and membership.
/api/v1/orgs/api/v1/orgs{"name":"My Lab","slug":"my-lab"}
/api/v1/orgs/{id}/api/v1/orgs/{id}{"name":"New Lab Name"}
/api/v1/orgs/{id}/api/v1/orgs/{id}/members/api/v1/orgs/{id}/members{"user_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","role":"member"}
/api/v1/orgs/{id}/members/{user_id}{"role":"admin"}
/api/v1/orgs/{id}/members/{user_id}A project scopes data, credentials and spend. Most work happens inside one.
/api/v1/projects/api/v1/projects{"name":"My Project","slug":"my-project","org_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}
/api/v1/projects/{id}/api/v1/projects/{id}{"name":"New Project Name"}
/api/v1/projects/{id}/api/v1/projects/{id}/jobs/api/v1/projects/{project_id}/collab/members/api/v1/projects/{project_id}/collab/members{"user_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","role":"contributor"}
/api/v1/projects/{project_id}/collab/members/{user_id}{"role":"admin"}
/api/v1/projects/{project_id}/collab/members/{user_id}/api/v1/projects/{project_id}/collab/invite{"email":"[email protected]","role":"viewer"}
/api/v1/projects/{project_id}/collab/invites/api/v1/projects/{project_id}/collab/activity/api/v1/projects/{project_id}/knowledge/activate{"corpus_slug":"materials-project"}
/api/v1/projects/{project_id}/knowledge/activations/api/v1/projects/{project_id}/knowledge/activations/{activation_id}/api/v1/projects/{project_id}/llm/models/api/v1/projects/{project_id}/llm/stream{"model":"claude-sonnet-4","messages":[{"role":"user","content":"..."}]}
/api/v1/projects/{project_id}/llm-keys/api/v1/projects/{project_id}/llm-keys{"provider":"openai","key":"sk-..."}
/api/v1/projects/{project_id}/llm-keys/{provider}/api/v1/projects/{project_id}/llm-keys/{provider}/rotate{"key":"sk-..."}
/api/v1/projects/{project_id}/mcp-services/api/v1/projects/{project_id}/mcp-services/{instance_id}/api/v1/projects/{project_id}/mcp-services/{instance_id}/proxy{"path":"/tools/list","body":{}}
/api/v1/projects/{project_id}/mcp-services/{instance_id}/scale{"replicas":1}
/api/v1/projects/{project_id}/conversations{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","title":"Alloy screening","metrics_json":{}}
/api/v1/projects/{project_id}/conversations/api/v1/projects/{id}/auto-route{"enabled":true}
/api/v1/projects/{project_id}/data-access/classes/api/v1/projects/{project_id}/data-access/grants/api/v1/projects/{project_id}/data-access/grants{"subject_type":"user","subject_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","data_class":"restricted","access":"read"}
/api/v1/projects/{project_id}/data-access/grants{"subject_type":"user","subject_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","data_class":"restricted"}
/api/v1/projects/{project_id}/data-access/meAccept an invitation to someone else's project.
/api/v1/invites/accept{"token":"..."}
Long-lived credentials for scripts, agents and CI.
/api/v1/api-keys/api/v1/api-keys{"project_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","scopes":["read","write"]}
/api/v1/api-keys/{id}The materials knowledge graph, semantic search over the corpus, and document ingestion.
/api/v1/knowledge/graph/stats/api/v1/knowledge/graph/search?q=titanium&limit=5/api/v1/knowledge/graph/entity/{entity_name}/api/v1/knowledge/graph/paths/api/v1/knowledge/graph/seed{"source_url":"..."}
/api/v1/knowledge/graph/ingest{"entities":[],"relationships":[]}
/api/v1/knowledge/admin/reconcile-vector-schema/api/v1/knowledge/admin/embed-graph/api/v1/knowledge/search{"query":"creep resistant superalloy","limit":5}
/api/v1/knowledge/embed{"doc_id":"my-doc","content":"..."}
/api/v1/knowledge/embed/bulk{"documents":[]}
/api/v1/knowledge/embeddings/stats/api/v1/knowledge/catalog/api/v1/knowledge/catalog/{slug}/api/v1/knowledge/ingest-job{"corpus_id":"...","source_url":"..."}
/api/v1/knowledge/ingest-job/{job_id}/api/v1/knowledge/ingest-jobs/api/v1/knowledge/research/query{"question":"...","depth":1}
/api/v1/knowledge/research/web-search{"query":"..."}
/api/v1/knowledge/capabilities/api/v1/knowledge/recall/api/v1/knowledge/ingest/holistic/stream/api/v1/knowledge/ingest/holistic/upload/api/v1/knowledge/research/search-webSubmit GPU work, estimate its cost before committing, then follow it to completion.
/api/v1/compute/gpus/api/v1/compute/providers/api/v1/compute/submit{"image":"my-model","gpu_type":"A100-80GB","inputs":{}}
/api/v1/compute/estimate{"image":"my-model","gpu_type":"A100-80GB","inputs":{}}
/api/v1/compute/{job_id}/api/v1/compute/{job_id}/logs/api/v1/compute/{job_id}/cancel/api/v1/compute/deployments/api/v1/compute/deployments{"name":"my-model","image":"repo/image:tag","target":"prism_node"}
/api/v1/compute/deployments/{id}/api/v1/compute/deployments/{id}/api/v1/compute/deployments/{id}/health/api/v1/compute/deployments/{id}/invoke/api/v1/compute/deployments/{id}/invoke/{*path}Published models, datasets and tools, with versions and download grants.
/api/v1/marketplace?status=approved/api/v1/marketplace/resources/api/v1/marketplace/search?q=titanium/api/v1/marketplace{"resource_type":"model","name":"...","slug":"..."}
/api/v1/marketplace/{slug}/api/v1/marketplace/{slug}{"description":"Updated description"}
/api/v1/marketplace/{slug}/api/v1/marketplace/{slug}/submit/api/v1/marketplace/{slug}/ontologyontology_id: my-ontology\nversion: 1.0.0\nclasses: []
/api/v1/marketplace/{slug}/purchase{"project_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}
/api/v1/marketplace/{slug}/versions/api/v1/marketplace/{slug}/versions{"version":"1.0.0"}
/api/v1/marketplace/{slug}/download/api/v1/marketplace/grants{"project_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","resource_id":"7c9e6679-7425-40de-944b-e07fc1f90ae7"}
/api/v1/marketplace/grants/{project_id}/{resource_id}/api/v1/marketplace/licensed-sources/resolve{"source_type":"thermodynamic_database","required_coverage":{"elements":["Mo","Nb"],"systems":[["Mo","Nb"]],"property_domains":[]}}
/api/v1/marketplace/resources/{slug}/api/v1/marketplace/resources/{slug}/install/api/v1/marketplace/{slug}/install/api/v1/marketplace/find{"query":"creep-resistant superalloy dataset","types":[],"limit":5}
Generic platform job submission and lifecycle.
/api/v1/jobs{"job_type":"simulation","project_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","payload":{}}
/api/v1/jobs/{id}/api/v1/jobs/{id}/cancel/api/v1/jobs/{id}/eventsOne synchronous call that starts a research run and blocks until it answers.
/api/v1/research{"question":"Which superalloys resist creep above 1000 C?"}
Server-side chat history, scoped to a project.
/api/v1/conversations/{id}/api/v1/conversations/{id}{"title":"Alloy screening v2"}
/api/v1/conversations/{id}/api/v1/conversations/{id}/messages{"messages":[{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","ordinal":0,"role":"user","content":"..."}]}
/api/v1/conversations/{id}/messagesGrounded chat answered against the corpus.
/api/v1/chat{"message":"Which superalloys resist creep above 1000 C?"}
Multi-agent deliberation: register a spec, run it, read the turns.
/api/v1/discourse/specs/api/v1/discourse/specs{"slug":"my-discourse","yaml":"..."}
/api/v1/discourse/specs/{id}/api/v1/discourse/run/{spec_id}{"inputs":{}}
/api/v1/discourse/{instance_id}/api/v1/discourse/{instance_id}/turnsDeclarative multi-step pipelines and their instances.
/api/v1/workflows/api/v1/workflows{"spec":"my-workflow","inputs":{}}
/api/v1/workflows/specs/api/v1/workflows/specs{"spec_yaml":"...","access":"public"}
/api/v1/workflows/{id}/api/v1/workflows/{id}/cancelRegister and reach compute nodes, including key exchange for encrypted transfer.
/api/v1/nodes/api/v1/nodes/live/api/v1/nodes/connect/api/v1/nodes/register{"name":"my-node","capabilities":{}}
/api/v1/nodes/{node_id}/api/v1/nodes/{id}/api/v1/nodes/{node_id}/heartbeat/api/v1/nodes/{node_id}/public-key/api/v1/nodes/{node_id}/exchange-key{"public_key":"base64..."}
/api/v1/nodes/spin-up{"name":"lab-a100","target":"own-hardware"}
/api/v1/nodes/{node_id}/tools/{tool}/invoke{"args":{}}
Brokered access to external materials databases using platform credentials.
/api/v1/data/materials-project{"formula":"Ni3Al","properties":["formation_energy_per_atom"]}
Model selection and orchestration over the platform's model pool.
/api/v1/mirdEvaluate an action against the platform's access policy.
/api/v1/policy/evaluate{"action":"read_data","resource":{"resource_type":"corpus","resource_id":"ntrs:19650021522"}}
Server-Sent Events tail of the durable platform event stream.
/api/v1/events/subscribeWhat has been consumed, by user, project or individual run.
/api/v1/usage/user/api/v1/usage/me/api/v1/usage/projects/{project_id}/api/v1/usage/projects/{project_id}/entries/api/v1/usage/runs/{run_id}Credit balance, prices, top-ups and per-category spend allowances.
/api/v1/billing/balance?project_id={project_id}/api/v1/billing/usage?period=monthly/api/v1/billing/history?page=1&per_page=50/api/v1/billing/prices/api/v1/billing/packages/api/v1/billing/topup{"package":"starter","project_id":"00000000-0000-0000-0000-000000000000"}
/api/v1/billing/allowances/api/v1/billing/allowances{"org_id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","category":"compute","monthly_credits":50000}
/api/v1/billing/subscribeRaise and track support tickets.
/api/v1/support/tickets/api/v1/support/tickets{"description":"...","type":"bug_report"}
/api/v1/support/tickets/{ticket_id}/api/v1/support/tickets/{ticket_id}{"status":"resolved"}
What a fresh install can do, read anonymously.
/api/v1/install/manifestThe platform's public key, so nodes can verify each other without calling home.
/api/v1/federation/platform-pubkeyOne endpoint spanning graph, platform and compute. See the schema above.
/api/v1/graphql{"query":"{ graphStats { nodes edges } }"}
/api/v1/graphqlThe machine-readable version of this page.
/api/v1/agent/capabilities/api/v1/account/storage/opt-in/api/v1/account/storage/opt-in{"enabled":true}
/api/v1/account/storage/object/api/v1/account/storage/object/api/v1/account/storage/list/api/v1/account/storage/delete{"path":"ontology/store.db"}
/api/v1/agents{"question":"How does rhenium affect creep in nickel superalloys?"}
/api/v1/agents/api/v1/agents/{id}/api/v1/agents/{id}/events/api/v1/agents/{id}/ws/api/v1/agents/{id}/cancel
Failures return a JSON body shaped
{"error": {"code": "…", "message": "…"}} with a matching HTTP status.
A 404 also carries a suggestions array naming the endpoints you most
likely meant, so a mistyped path tells you how to fix itself.