Docs · API & MCP

Evidenced answers via API.

The c:node Contract API delivers answers, legal provisions and public administration services with source, licence and verification status. You call it via REST or plug it into Claude, Copilot and your own agents directly via MCP.

Overview

The Contract API is the public interface to the c:node Graph. Every answer is built so that you can verify it: it names the source (ref), the verification status (grounding), the licence and, where required, the attribution of the data source.

Base URLhttps://contract.c-node.ai
FormatJSON · Server-Sent Events
Versionv1 · OpenAPI 3

The evidence fields

FieldMeaning
refStandard reference of the source, e.g. ELI:BSIGesetz§10, CELEX:32024R1689 or XZUFI:S1000030000000045.
groundingVerification status against the cited passage, e.g. verified.
licenseLicence class of the source: open, attribution or internal.
attributionsMandatory attributions (source, licence, URL) for the data delivered.
citations · factscoreFor /v1/ask: verified sources only, plus a verdict per statement (belegt = evidenced or offen = open) and the share of evidenced statements.
content_hashFor provenance records: SHA-256 over the content, for logging under EU AI Act Art. 12.

The complete machine-readable specification is available at /openapi.json.

Quickstart

The first two calls work against the sandbox without a key. For knowledge endpoints you need a Contract key.

1 · Check the connection
curl https://contract.c-node.ai/v1/health
2 · Fetch a provenance record (no key)
curl "https://contract.c-node.ai/v1/provenance?ref=CELEX:32024R1689"
3 · With a key: all sections of a law
curl "https://contract.c-node.ai/v1/legal?law=BSIGesetz&limit=2" \ -H "X-API-Key: $CNODE_API_KEY"
Python
import os, httpx r = httpx.get("https://contract.c-node.ai/v1/ask", params={"q": "What obligations do providers of high-risk AI have?"}, headers={"X-API-Key": os.environ["CNODE_API_KEY"]}, timeout=60) answer = r.json() print(answer["answer"], answer["citations"])

Authentication

Send your Contract key in the X-API-Key header. The query parameter ?key= is also accepted, but ends up in logs and browser histories more easily – only use it where a header is not possible.

curl https://contract.c-node.ai/v1/profiles -H "X-API-Key: $CNODE_API_KEY"
  • Without a key you land in the sandbox (profile public-observatory): graph overview, provenance, audit and attributions.
  • Contract key: bound to a profile, unlocks /v1/ask, /v1/legal, /v1/leistung and /v1/betroffenheit.
  • Tenant key: additionally bound to your own tenant graph – for Company Brain, findings and ingest. Answers then combine the c:node Graph with your own knowledge.
Keys belong on the server. Store the key in an environment variable or your secret store, never in frontend code or a repository. You get keys with your plan or via a short call.

Profiles & scope

Every key is bound to a profile. The profile defines which licence classes and knowledge domains an answer may use – the models only see what your profile allows. GET /v1/profiles lists them live.

ProfilePurposeKey
public-observatoryPublic sandbox: graph overview and provenance.no
trialTrial access for evaluation.yes
free-marketMarket knowledge (markets, trade, investment, public finances).yes
research-openResearch partners: research and innovation.yes
de-federalGerman federal data space, full access.yes
commercial-fullCommercial full access (excluding non-commercial sources).yes

MCP: c:node in Claude, Copilot & your agents

The c:node MCP server exposes the Contract API as tools. The model writes, c:node delivers the evidenced basis: ask Claude for a legal basis and it calls cnode_ask and answers with a source.

claude mcp add --transport http cnode https://mcp.c-node.ai/mcp \ --header "X-API-Key: $CNODE_API_KEY"

Add to .vscode/mcp.json. Copilot asks for the key on first start and does not store it in the project:

{ "inputs": [{ "type": "promptString", "id": "cnode-key", "description": "c:node Contract key", "password": true }], "servers": { "cnode": { "type": "http", "url": "https://mcp.c-node.ai/mcp", "headers": { "X-API-Key": "${input:cnode-key}" } } } }

Any MCP client with Streamable HTTP works: URL https://mcp.c-node.ai/mcp, key in the X-API-Key header or as Authorization: Bearer <key>. Usage and profile then run through your own key. In on-prem deployments the MCP server runs in your environment and talks to your own Contract API.

Tools

ToolWhat it doesEndpoint
cnode_askEvidenced answer to a question, every statement with a source.GET /v1/ask
cnode_legalSection by reference, all sections of a law or full-text search.GET /v1/legal
cnode_leistungPublic administration service with its legal basis.GET /v1/leistung
cnode_dossierHash-chained application dossier. Prepares, triggers nothing.POST /v1/dossier
cnode_brain_previewCompany Brain from a domain, without storing.GET /v1/demo/brain/stream
cnode_brain_bootstrapBuild and store the Company Brain for your tenant.POST /v1/brain/bootstrap
cnode_findingsCurrent findings for your tenant, each with evidence.GET /v1/findings
cnode_health · cnode_profilesConnection check and the profiles of your key.GET /v1/health · /v1/profiles

Self-hosting (open core)

The c:node shell is open core: interface, chat and graph runtime run via Docker on your machine or server. For local answers an open model via Ollama is enough – or you bring your own API key.

LicenceAGPL-3.0 · commercial licence available
RequirementDocker + Docker Compose
Local endpointsShell :3010 · API :8080
Quickstart
git clone https://github.com/CreativateLabs/cnode-shell cd cnode-shell cp .env.example .env # adjust if needed docker compose up --build
Optional: local model
ollama pull qwen2.5:7b

The shell then runs at http://localhost:3010 and the API at http://localhost:8080. The scope of the open core, tenant configuration and the commercial licence are described in the README on GitHub.

What is open, what isn't? The interface and graph runtime are open – a working base, air-gapped too, that you can run and audit yourself. The trained c:node intelligence with the c:node Graph for law, registers and market, plus operation with an SLA, is available in the plans.

Knowledge

Evidenced answers and legal sources. All endpoints here require a Contract key.

GET/v1/askEvidenced answer to a questionKey

Answers a question exclusively from the concepts your profile allows. Citations come only from verified references. If c:node finds no evidence, the answer says so instead of guessing.

ParameterDescription
qThe question in natural language (min. 3 characters). Required.
kNumber of concepts the answer draws on (1–20, default 6).
Response · structure (shortened)
{ "question": "What obligations do providers of high-risk AI systems have?", "grounded": true, "answer": "… [CELEX:32024R1689] …", "citations": ["CELEX:32024R1689"], "verdict": "…", "factscore": 1.0, "verification": [ { "claim": "…", "verdict": "belegt", "source": "CELEX:32024R1689", "via": "citation" } ], "profile": "de-federal", "attributions": [] }

Without evidence: "grounded": false and the answer “That is not (yet) in the knowledge graph.” Statements without support receive the verdict offen (open).

GET/v1/ask/streamThe same as a stream (SSE)Key

Same parameters and verification as /v1/ask. The response arrives as server-sent events: token events with text chunks, then a done event with citations, verdict and factscore, and finally [DONE].

curl -N "https://contract.c-node.ai/v1/ask/stream?q=Meldepflicht%20Wohnsitz" \ -H "X-API-Key: $CNODE_API_KEY" data: {"type": "token", "text": "Die Anmeldung …"} data: {"type": "done", "citations": […], "factscore": …, "attributions": […]} data: [DONE]
GET/v1/legalLegal provisions (ELI / CELEX)Key

One section by reference, all sections of a law or a full-text search. One of the three parameters is required.

ParameterDescription
refExact reference, e.g. ELI:BSIGesetz§1.
lawName of the law, e.g. BSIGesetz – returns its sections.
qFull-text search (all terms must appear).
limit · offsetPagination (1–500, default 50). If there are more hits, next_offset is included in the response.
Response · real, text shortened (source text in German)
{ "profile": "de-federal", "total": 66, "count": 2, "limit": 2, "offset": 0, "next_offset": 2, "results": [ { "label": "BSIGesetzPar10", "ref": "ELI:BSIGesetz§10", "std": "ELI", "text": "Anordnungen von Maßnahmen zur Abwendung oder Behebung von Sicherheitsvorfällen. …", "grounding": "verified", "license": "open" } ], "attributions": [] }
GET/v1/leistungPublic administration services with legal basisKey

Public administration services from XZuFi/LeiKa (German service catalogues). rechtsgrundlagen (legal bases) only contains links to laws that are in the c:node Graph – nothing is guessed. Parameters: ref or q, plus limit/offset.

Response · real (source data in German)
{ "profile": "de-federal", "total": 2, "count": 1, "results": [ { "label": "LeistungS1000030000000045", "ref": "XZUFI:S1000030000000045", "bezeichnung": "Wohnsitz Anmeldung als Hauptwohnsitz — Verwaltungsleistung (XZuFi/LeiKa, …)", "license": "attribution", "rechtsgrundlagen": [] } ], "attributions": [ { "source": "Freie Hansestadt Bremen — Bürgerservice (XZuFi/FIM)", "license": "Datenlizenz Deutschland (dl-de/by-2-0)", "url": "https://www.govdata.de" } ] }

Provenance & audit

Records for traceability: where a statement comes from, whom a legal act affects, and which sources must be attributed. With Try it you call the sandbox live.

GET/v1/provenanceProvenance record for a referenceno key

Returns the verification status, licence, an uncertainty statement and a content hash for a reference – built for logging under EU AI Act Art. 12. Parameter: ref.

GET/v1/auditWhich companies does a legal act affect?no key

Links an EU legal act to the affected sectors and companies from the commercial register. Parameter: act, e.g. ArtificialIntelligenceAct.

GET/v1/betroffenheitRegional impact per legal actKey

Extends /v1/audit with the region: law → sector → affected companies → federal state → regional indicators (GDP, unemployment rate, income). Every derived figure carries its evidence chain. Parameters: act (optional), limit (1–100).

POST/v1/dossierHash-chained application dossierKey

Assembles a verifiable dossier from application fields: every field with its source, the eIDAS trust verdict on the seal and a tamper-proof hash chain. If the application names a service without legal bases, c:node adds them from the graph. Responses contain personal data and are not cached.

curl -X POST https://contract.c-node.ai/v1/dossier \ -H "X-API-Key: $CNODE_API_KEY" -H "Content-Type: application/json" \ -d '{ "leistung": "XZUFI:S1000030000000045", "felder": [ { "name": "Address", "wert": "…", "quelle": "Certificate of registration", "siegel": { "aussteller": "…", "typ": "…" } } ] }'
GET/v1/attributionsMandatory attributionsno key

All data sources of your profile with licence and URL – for your imprint, source list or export.

Company Brain

A domain becomes an evidenced company profile: c:node reads the public pages, checks the imprint and commercial register, anchors the company in its sector and delivers findings on regulation and open public tenders – each with a source.

GET/v1/demo/brain/streamPreview from a domain (SSE)no key

The public preview: streams the run for a domain, stores nothing. Limited per IP and day; the result for a domain is cached for 24 hours and replayed. Parameter: domain, e.g. firma.de.

Event types in this order: step, page, feed, impressum, register, profile, anchor, finding, done (on errors error), terminated by [DONE].

curl -N "https://contract.c-node.ai/v1/demo/brain/stream?domain=firma.de"
POST/v1/brain/bootstrapBuild the Brain for your tenantTenant key

Runs the full process and stores profile, pages and findings in your tenant graph. Afterwards /v1/ask and /v1/findings know your company. Body: {"domain": "firma.de"}. Time limit 90 seconds (504 if exceeded).

As a stream: GET /v1/brain/stream?domain=… delivers the same events as the preview and stores at the end.

GET/v1/findingsCurrent findings for your tenantTenant key

The proactive findings from the last run: regulation, public tenders, registers and sector context, each with evidence. If there has been no run yet, findings is empty and hint names the next step.

Tenant graph

POST/v1/ingestAdd your own knowledgeTenant key

Writes a document or note into your private tenant graph. The entry can be answered immediately via /v1/ask. The c:node Graph itself remains unchanged.

curl -X POST https://contract.c-node.ai/v1/ingest \ -H "X-API-Key: $CNODE_API_KEY" -H "Content-Type: application/json" \ -d '{"title": "Procurement policy 2026", "text": "…", "source": "Intranet"}' → { "ok": true, "tenant": "…", "concept": "Procurement policy 2026", "ref": "tenant:…:procurement-policy-2026", "how": "…", "embedded": true }

Fields: title or label, text or content, optionally source and ref.

Operations

GET/v1/healthAPI statusno key
GET/v1/profilesProfiles and what they may seeno key
GET/v1/usageUsage and rate limitno key

Shows your current per-minute quota and usage: answers delivered, of which billable, ingests and the average factscore.

GET/v1/graphc:node Graph metricsno key

Concepts, relations, domains and verification rate of the graph your profile sees.

Errors & limits

Errors are returned as JSON with a detail field.

StatusMeaning
400Parameter missing, e.g. /v1/legal without ref, law or q.
401Missing or invalid key for an endpoint that requires a Contract key.
403Key valid, but without a tenant (Company Brain, findings, ingest).
404Reference or legal act not in the graph.
429Rate limit reached. Wait the number of seconds given in the Retry-After header.
503Answer generation is currently at capacity. Retry after Retry-After.
504Brain run exceeded the time limit.

Every /v1 call except /v1/health is rate-limited per client; /v1/usage shows your current quota. Only a pseudonymous client ID, the path and the status are logged – no content.